google-genai 0.8.0__tar.gz → 1.3.0__tar.gz

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.
Files changed (32) hide show
  1. {google_genai-0.8.0 → google_genai-1.3.0}/PKG-INFO +373 -189
  2. {google_genai-0.8.0 → google_genai-1.3.0}/README.md +370 -188
  3. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/_api_client.py +163 -56
  4. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/_api_module.py +5 -0
  5. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/_automatic_function_calling_util.py +34 -35
  6. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/_common.py +36 -1
  7. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/_extra_utils.py +21 -10
  8. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/_replay_api_client.py +34 -1
  9. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/_transformers.py +100 -24
  10. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/batches.py +6 -3
  11. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/caches.py +13 -10
  12. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/chats.py +24 -8
  13. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/client.py +22 -11
  14. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/errors.py +22 -3
  15. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/files.py +27 -18
  16. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/live.py +69 -41
  17. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/models.py +1020 -133
  18. google_genai-0.8.0/google/genai/_operations.py → google_genai-1.3.0/google/genai/operations.py +260 -20
  19. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/tunings.py +227 -60
  20. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/types.py +580 -82
  21. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/version.py +1 -1
  22. {google_genai-0.8.0 → google_genai-1.3.0}/google_genai.egg-info/PKG-INFO +373 -189
  23. {google_genai-0.8.0 → google_genai-1.3.0}/google_genai.egg-info/SOURCES.txt +1 -1
  24. {google_genai-0.8.0 → google_genai-1.3.0}/google_genai.egg-info/requires.txt +2 -0
  25. {google_genai-0.8.0 → google_genai-1.3.0}/pyproject.toml +3 -1
  26. {google_genai-0.8.0 → google_genai-1.3.0}/LICENSE +0 -0
  27. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/__init__.py +0 -0
  28. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/_test_api_client.py +0 -0
  29. {google_genai-0.8.0 → google_genai-1.3.0}/google/genai/pagers.py +0 -0
  30. {google_genai-0.8.0 → google_genai-1.3.0}/google_genai.egg-info/dependency_links.txt +0 -0
  31. {google_genai-0.8.0 → google_genai-1.3.0}/google_genai.egg-info/top_level.txt +0 -0
  32. {google_genai-0.8.0 → google_genai-1.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: google-genai
3
- Version: 0.8.0
3
+ Version: 1.3.0
4
4
  Summary: GenAI Python SDK
5
5
  Author-email: Google LLC <googleapis-packages@google.com>
6
6
  License: Apache-2.0
@@ -21,9 +21,11 @@ Requires-Python: >=3.9
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
23
  Requires-Dist: google-auth<3.0.0dev,>=2.14.1
24
+ Requires-Dist: httpx<1.0.0dev,>=0.28.1
24
25
  Requires-Dist: pydantic<3.0.0dev,>=2.0.0
25
26
  Requires-Dist: requests<3.0.0dev,>=2.28.1
26
27
  Requires-Dist: websockets<15.0dev,>=13.0
28
+ Requires-Dist: typing-extensions<5.0.0dev,>=4.11.0
27
29
 
28
30
  # Google Gen AI SDK
29
31
 
@@ -34,7 +36,7 @@ Requires-Dist: websockets<15.0dev,>=13.0
34
36
 
35
37
  -----
36
38
 
37
- Google Gen AI Python SDK provides an interface for developers to integrate Google's generative models into their Python applications. It supports the [Gemini Developer API](https://ai.google.dev/gemini-api/docs) and [Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview) APIs. This is an early release. API is subject to change. Please do not use this SDK in production environments at this stage.
39
+ Google Gen AI Python SDK provides an interface for developers to integrate Google's generative models into their Python applications. It supports the [Gemini Developer API](https://ai.google.dev/gemini-api/docs) and [Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview) APIs.
38
40
 
39
41
  ## Installation
40
42
 
@@ -56,13 +58,65 @@ different services ([Gemini Developer API](https://ai.google.dev/gemini-api/docs
56
58
 
57
59
  ```python
58
60
  # Only run this block for Gemini Developer API
59
- client = genai.Client(api_key="GEMINI_API_KEY")
61
+ client = genai.Client(api_key='GEMINI_API_KEY')
60
62
  ```
61
63
 
62
64
  ```python
63
65
  # Only run this block for Vertex AI API
64
66
  client = genai.Client(
65
- vertexai=True, project="your-project-id", location="us-central1"
67
+ vertexai=True, project='your-project-id', location='us-central1'
68
+ )
69
+ ```
70
+
71
+ **(Optional) Using environment variables:**
72
+
73
+ You can create a client by configuring the necessary environment variables.
74
+ Configuration setup instructions depends on whether you're using the Gemini API
75
+ on Vertex AI or the ML Dev Gemini API.
76
+
77
+ **ML Dev Gemini API:** Set `GOOGLE_API_KEY` as shown below:
78
+
79
+ ```bash
80
+ export GOOGLE_API_KEY='your-api-key'
81
+ ```
82
+
83
+ **Vertex AI API:** Set `GOOGLE_GENAI_USE_VERTEXAI`, `GOOGLE_CLOUD_PROJECT`
84
+ and `GOOGLE_CLOUD_LOCATION`, as shown below:
85
+
86
+ ```bash
87
+ export GOOGLE_GENAI_USE_VERTEXAI=true
88
+ export GOOGLE_CLOUD_PROJECT='your-project-id'
89
+ export GOOGLE_CLOUD_LOCATION='us-central1'
90
+ ```
91
+
92
+ ```python
93
+ client = genai.Client()
94
+ ```
95
+
96
+ ### API Selection
97
+
98
+ By default, the SDK uses the beta API endpoints provided by Google to support
99
+ preview features in the APIs. The stable API endpoints can be selected by
100
+ setting the API version to `v1`.
101
+
102
+ To set the API version use `http_options`. For example, to set the API version
103
+ to `v1` for Vertex AI:
104
+
105
+ ```python
106
+ client = genai.Client(
107
+ vertexai=True,
108
+ project='your-project-id',
109
+ location='us-central1',
110
+ http_options=types.HttpOptions(api_version='v1')
111
+ )
112
+ ```
113
+
114
+ To set the API version to `v1alpha` for the Gemini Developer API:
115
+
116
+ ```python
117
+ client = genai.Client(
118
+ api_key='GEMINI_API_KEY',
119
+ http_options=types.HttpOptions(api_version='v1alpha')
66
120
  )
67
121
  ```
68
122
 
@@ -82,7 +136,7 @@ The `client.models` modules exposes model inferencing and model getters.
82
136
 
83
137
  ```python
84
138
  response = client.models.generate_content(
85
- model="gemini-2.0-flash-exp", contents="why is the sky blue?"
139
+ model='gemini-2.0-flash-001', contents='Why is the sky blue?'
86
140
  )
87
141
  print(response.text)
88
142
  ```
@@ -90,29 +144,60 @@ print(response.text)
90
144
  #### with uploaded file (Gemini API only)
91
145
  download the file in console.
92
146
 
93
- ```cmd
147
+ ```sh
94
148
  !wget -q https://storage.googleapis.com/generativeai-downloads/data/a11.txt
95
149
  ```
96
150
 
97
151
  python code.
98
152
 
99
153
  ```python
100
- file = client.files.upload(path="a11.txt")
154
+ file = client.files.upload(file='a11.txt')
101
155
  response = client.models.generate_content(
102
- model="gemini-2.0-flash-exp",
103
- contents=["Could you summarize this file?", file]
156
+ model='gemini-2.0-flash-001',
157
+ contents=['Could you summarize this file?', file]
104
158
  )
105
159
  print(response.text)
106
160
  ```
107
161
 
162
+ #### How to structure `contents`
163
+ There are several ways to structure the `contents` in your request.
164
+
165
+ Provide a single string as shown in the text example above:
166
+
167
+ ```python
168
+ contents='Can you recommend some things to do in Boston and New York in the winter?'
169
+ ```
170
+
171
+ Provide a single `Content` instance with multiple `Part` instances:
172
+
173
+ ```python
174
+ contents=types.Content(parts=[
175
+ types.Part.from_text(text='Can you recommend some things to do in Boston in the winter?'),
176
+ types.Part.from_text(text='Can you recommend some things to do in New York in the winter?')
177
+ ], role='user')
178
+ ```
179
+
180
+ When sending more than one input type, provide a list with multiple `Content`
181
+ instances:
182
+
183
+ ```python
184
+ contents=[
185
+ 'What is this a picture of?',
186
+ types.Part.from_uri(
187
+ file_uri='gs://generativeai-downloads/images/scones.jpg',
188
+ mime_type='image/jpeg',
189
+ ),
190
+ ],
191
+ ```
192
+
108
193
  ### System Instructions and Other Configs
109
194
 
110
195
  ```python
111
196
  response = client.models.generate_content(
112
- model="gemini-2.0-flash-exp",
113
- contents="high",
197
+ model='gemini-2.0-flash-001',
198
+ contents='high',
114
199
  config=types.GenerateContentConfig(
115
- system_instruction="I say high, you say low",
200
+ system_instruction='I say high, you say low',
116
201
  temperature=0.3,
117
202
  ),
118
203
  )
@@ -126,8 +211,8 @@ dictionaries. You can get the type from `google.genai.types`.
126
211
 
127
212
  ```python
128
213
  response = client.models.generate_content(
129
- model="gemini-2.0-flash-exp",
130
- contents=types.Part.from_text(text="Why is the sky blue?"),
214
+ model='gemini-2.0-flash-001',
215
+ contents=types.Part.from_text(text='Why is the sky blue?'),
131
216
  config=types.GenerateContentConfig(
132
217
  temperature=0,
133
218
  top_p=0.95,
@@ -135,7 +220,7 @@ response = client.models.generate_content(
135
220
  candidate_count=1,
136
221
  seed=5,
137
222
  max_output_tokens=100,
138
- stop_sequences=["STOP!"],
223
+ stop_sequences=['STOP!'],
139
224
  presence_penalty=0.0,
140
225
  frequency_penalty=0.0,
141
226
  ),
@@ -144,53 +229,17 @@ response = client.models.generate_content(
144
229
  print(response.text)
145
230
  ```
146
231
 
147
- ### Thinking
148
-
149
- The Gemini 2.0 Flash Thinking model is an experimental model that could return
150
- "thoughts" as part of its response.
151
-
152
- #### Gemini Developer API
153
-
154
- Thinking config is only available in v1alpha for Gemini AI API.
155
-
156
- ```python
157
- response = client.models.generate_content(
158
- model='gemini-2.0-flash-thinking-exp',
159
- contents='What is the sum of natural numbers from 1 to 100?',
160
- config=types.GenerateContentConfig(
161
- thinking_config=types.ThinkingConfig(include_thoughts=True),
162
- http_options=types.HttpOptions(api_version='v1alpha'),
163
- )
164
- )
165
- for part in response.candidates[0].content.parts:
166
- print(part)
167
- ```
168
-
169
- #### Vertex AI API
170
-
171
- ```python
172
- response = client.models.generate_content(
173
- model='gemini-2.0-flash-thinking-exp-01-21',
174
- contents='What is the sum of natural numbers from 1 to 100?',
175
- config=types.GenerateContentConfig(
176
- thinking_config=types.ThinkingConfig(include_thoughts=True),
177
- )
178
- )
179
- for part in response.candidates[0].content.parts:
180
- print(part)
181
- ```
182
-
183
232
  ### List Base Models
184
233
 
185
234
  To retrieve tuned models, see [list tuned models](#list-tuned-models).
186
235
 
187
236
  ```python
188
- for model in client.models.list(config={'query_base':True}):
237
+ for model in client.models.list():
189
238
  print(model)
190
239
  ```
191
240
 
192
241
  ```python
193
- pager = client.models.list(config={"page_size": 10, 'query_base':True})
242
+ pager = client.models.list(config={'page_size': 10})
194
243
  print(pager.page_size)
195
244
  print(pager[0])
196
245
  pager.next_page()
@@ -200,12 +249,12 @@ print(pager[0])
200
249
  #### Async
201
250
 
202
251
  ```python
203
- async for job in await client.aio.models.list(config={'query_base':True}):
252
+ async for job in await client.aio.models.list():
204
253
  print(job)
205
254
  ```
206
255
 
207
256
  ```python
208
- async_pager = await client.aio.models.list(config={"page_size": 10, 'query_base':True})
257
+ async_pager = await client.aio.models.list(config={'page_size': 10})
209
258
  print(async_pager.page_size)
210
259
  print(async_pager[0])
211
260
  await async_pager.next_page()
@@ -216,13 +265,13 @@ print(async_pager[0])
216
265
 
217
266
  ```python
218
267
  response = client.models.generate_content(
219
- model="gemini-2.0-flash-exp",
220
- contents="Say something bad.",
268
+ model='gemini-2.0-flash-001',
269
+ contents='Say something bad.',
221
270
  config=types.GenerateContentConfig(
222
271
  safety_settings=[
223
272
  types.SafetySetting(
224
- category="HARM_CATEGORY_HATE_SPEECH",
225
- threshold="BLOCK_ONLY_HIGH",
273
+ category='HARM_CATEGORY_HATE_SPEECH',
274
+ threshold='BLOCK_ONLY_HIGH',
226
275
  )
227
276
  ]
228
277
  ),
@@ -235,7 +284,7 @@ print(response.text)
235
284
  #### Automatic Python function Support
236
285
 
237
286
  You can pass a Python function directly and it will be automatically
238
- called and responded.
287
+ called and responded by default.
239
288
 
240
289
  ```python
241
290
  def get_current_weather(location: str) -> str:
@@ -244,17 +293,41 @@ def get_current_weather(location: str) -> str:
244
293
  Args:
245
294
  location: The city and state, e.g. San Francisco, CA
246
295
  """
247
- return "sunny"
296
+ return 'sunny'
248
297
 
249
298
 
250
299
  response = client.models.generate_content(
251
- model="gemini-2.0-flash-exp",
252
- contents="What is the weather like in Boston?",
300
+ model='gemini-2.0-flash-001',
301
+ contents='What is the weather like in Boston?',
253
302
  config=types.GenerateContentConfig(tools=[get_current_weather]),
254
303
  )
255
304
 
256
305
  print(response.text)
257
306
  ```
307
+ #### Disabling automatic function calling
308
+ If you pass in a python function as a tool directly, and do not want
309
+ automatic function calling, you can disable automatic function calling
310
+ as follows:
311
+
312
+ ```python
313
+ response = client.models.generate_content(
314
+ model='gemini-2.0-flash-001',
315
+ contents='What is the weather like in Boston?',
316
+ config=types.GenerateContentConfig(
317
+ tools=[get_current_weather],
318
+ automatic_function_calling=types.AutomaticFunctionCallingConfig(
319
+ disable=True
320
+ ),
321
+ ),
322
+ )
323
+ ```
324
+
325
+ With automatic function calling disabled, you will get a list of function call
326
+ parts in the response:
327
+
328
+ ```python
329
+ function_calls: Optional[List[types.FunctionCall]] = response.function_calls
330
+ ```
258
331
 
259
332
  #### Manually declare and invoke a function for function calling
260
333
 
@@ -266,25 +339,25 @@ Then you will receive a function call part in the response.
266
339
 
267
340
  ```python
268
341
  function = types.FunctionDeclaration(
269
- name="get_current_weather",
270
- description="Get the current weather in a given location",
342
+ name='get_current_weather',
343
+ description='Get the current weather in a given location',
271
344
  parameters=types.Schema(
272
- type="OBJECT",
345
+ type='OBJECT',
273
346
  properties={
274
- "location": types.Schema(
275
- type="STRING",
276
- description="The city and state, e.g. San Francisco, CA",
347
+ 'location': types.Schema(
348
+ type='STRING',
349
+ description='The city and state, e.g. San Francisco, CA',
277
350
  ),
278
351
  },
279
- required=["location"],
352
+ required=['location'],
280
353
  ),
281
354
  )
282
355
 
283
356
  tool = types.Tool(function_declarations=[function])
284
357
 
285
358
  response = client.models.generate_content(
286
- model="gemini-2.0-flash-exp",
287
- contents="What is the weather like in Boston?",
359
+ model='gemini-2.0-flash-001',
360
+ contents='What is the weather like in Boston?',
288
361
  config=types.GenerateContentConfig(tools=[tool]),
289
362
  )
290
363
 
@@ -298,33 +371,34 @@ The following example shows how to do it for a simple function invocation.
298
371
 
299
372
  ```python
300
373
  user_prompt_content = types.Content(
301
- role="user",
302
- parts=[types.Part.from_text(text="What is the weather like in Boston?")],
374
+ role='user',
375
+ parts=[types.Part.from_text(text='What is the weather like in Boston?')],
303
376
  )
304
377
  function_call_part = response.function_calls[0]
378
+ function_call_content = response.candidates[0].content
305
379
 
306
380
 
307
381
  try:
308
382
  function_result = get_current_weather(
309
383
  **function_call_part.function_call.args
310
384
  )
311
- function_response = {"result": function_result}
385
+ function_response = {'result': function_result}
312
386
  except (
313
387
  Exception
314
388
  ) as e: # instead of raising the exception, you can let the model handle it
315
- function_response = {"error": str(e)}
389
+ function_response = {'error': str(e)}
316
390
 
317
391
 
318
392
  function_response_part = types.Part.from_function_response(
319
- name=function_call_part.function_call.name,
393
+ name=function_call_part.name,
320
394
  response=function_response,
321
395
  )
322
396
  function_response_content = types.Content(
323
- role="tool", parts=[function_response_part]
397
+ role='tool', parts=[function_response_part]
324
398
  )
325
399
 
326
400
  response = client.models.generate_content(
327
- model="gemini-2.0-flash-exp",
401
+ model='gemini-2.0-flash-001',
328
402
  contents=[
329
403
  user_prompt_content,
330
404
  function_call_content,
@@ -338,6 +412,66 @@ response = client.models.generate_content(
338
412
  print(response.text)
339
413
  ```
340
414
 
415
+ #### Function calling with `ANY` tools config mode
416
+
417
+ If you configure function calling mode to be `ANY`, then the model will always
418
+ return function call parts. If you also pass a python function as a tool, by
419
+ default the SDK will perform automatic function calling until the remote calls exceed the
420
+ maximum remote call for automatic function calling (default to 10 times).
421
+
422
+ If you'd like to disable automatic function calling in `ANY` mode:
423
+
424
+ ```python
425
+ def get_current_weather(location: str) -> str:
426
+ """Returns the current weather.
427
+
428
+ Args:
429
+ location: The city and state, e.g. San Francisco, CA
430
+ """
431
+ return "sunny"
432
+
433
+ response = client.models.generate_content(
434
+ model="gemini-2.0-flash-001",
435
+ contents="What is the weather like in Boston?",
436
+ config=types.GenerateContentConfig(
437
+ tools=[get_current_weather],
438
+ automatic_function_calling=types.AutomaticFunctionCallingConfig(
439
+ disable=True
440
+ ),
441
+ tool_config=types.ToolConfig(
442
+ function_calling_config=types.FunctionCallingConfig(mode='ANY')
443
+ ),
444
+ ),
445
+ )
446
+ ```
447
+
448
+ If you'd like to set `x` number of automatic function call turns, you can
449
+ configure the maximum remote calls to be `x + 1`.
450
+ Assuming you prefer `1` turn for automatic function calling.
451
+
452
+ ```python
453
+ def get_current_weather(location: str) -> str:
454
+ """Returns the current weather.
455
+
456
+ Args:
457
+ location: The city and state, e.g. San Francisco, CA
458
+ """
459
+ return "sunny"
460
+
461
+ response = client.models.generate_content(
462
+ model="gemini-2.0-flash-001",
463
+ contents="What is the weather like in Boston?",
464
+ config=types.GenerateContentConfig(
465
+ tools=[get_current_weather],
466
+ automatic_function_calling=types.AutomaticFunctionCallingConfig(
467
+ maximum_remote_calls=2
468
+ ),
469
+ tool_config=types.ToolConfig(
470
+ function_calling_config=types.FunctionCallingConfig(mode='ANY')
471
+ ),
472
+ ),
473
+ )
474
+ ```
341
475
  ### JSON Response Schema
342
476
 
343
477
  #### Pydantic Model Schema support
@@ -359,10 +493,10 @@ class CountryInfo(BaseModel):
359
493
 
360
494
 
361
495
  response = client.models.generate_content(
362
- model="gemini-2.0-flash-exp",
363
- contents="Give me information for the United States.",
496
+ model='gemini-2.0-flash-001',
497
+ contents='Give me information for the United States.',
364
498
  config=types.GenerateContentConfig(
365
- response_mime_type="application/json",
499
+ response_mime_type='application/json',
366
500
  response_schema=CountryInfo,
367
501
  ),
368
502
  )
@@ -371,30 +505,30 @@ print(response.text)
371
505
 
372
506
  ```python
373
507
  response = client.models.generate_content(
374
- model="gemini-2.0-flash-exp",
375
- contents="Give me information for the United States.",
508
+ model='gemini-2.0-flash-001',
509
+ contents='Give me information for the United States.',
376
510
  config=types.GenerateContentConfig(
377
- response_mime_type="application/json",
511
+ response_mime_type='application/json',
378
512
  response_schema={
379
- "required": [
380
- "name",
381
- "population",
382
- "capital",
383
- "continent",
384
- "gdp",
385
- "official_language",
386
- "total_area_sq_mi",
513
+ 'required': [
514
+ 'name',
515
+ 'population',
516
+ 'capital',
517
+ 'continent',
518
+ 'gdp',
519
+ 'official_language',
520
+ 'total_area_sq_mi',
387
521
  ],
388
- "properties": {
389
- "name": {"type": "STRING"},
390
- "population": {"type": "INTEGER"},
391
- "capital": {"type": "STRING"},
392
- "continent": {"type": "STRING"},
393
- "gdp": {"type": "INTEGER"},
394
- "official_language": {"type": "STRING"},
395
- "total_area_sq_mi": {"type": "INTEGER"},
522
+ 'properties': {
523
+ 'name': {'type': 'STRING'},
524
+ 'population': {'type': 'INTEGER'},
525
+ 'capital': {'type': 'STRING'},
526
+ 'continent': {'type': 'STRING'},
527
+ 'gdp': {'type': 'INTEGER'},
528
+ 'official_language': {'type': 'STRING'},
529
+ 'total_area_sq_mi': {'type': 'INTEGER'},
396
530
  },
397
- "type": "OBJECT",
531
+ 'type': 'OBJECT',
398
532
  },
399
533
  ),
400
534
  )
@@ -417,7 +551,7 @@ class InstrumentEnum(Enum):
417
551
  KEYBOARD = 'Keyboard'
418
552
 
419
553
  response = client.models.generate_content(
420
- model='gemini-2.0-flash-exp',
554
+ model='gemini-2.0-flash-001',
421
555
  contents='What instrument plays multiple notes at once?',
422
556
  config={
423
557
  'response_mime_type': 'text/x.enum',
@@ -442,7 +576,7 @@ class InstrumentEnum(Enum):
442
576
  KEYBOARD = 'Keyboard'
443
577
 
444
578
  response = client.models.generate_content(
445
- model='gemini-2.0-flash-exp',
579
+ model='gemini-2.0-flash-001',
446
580
  contents='What instrument plays multiple notes at once?',
447
581
  config={
448
582
  'response_mime_type': 'application/json',
@@ -458,9 +592,9 @@ print(response.text)
458
592
 
459
593
  ```python
460
594
  for chunk in client.models.generate_content_stream(
461
- model="gemini-2.0-flash-exp", contents="Tell me a story in 300 words."
595
+ model='gemini-2.0-flash-001', contents='Tell me a story in 300 words.'
462
596
  ):
463
- print(chunk.text, end="")
597
+ print(chunk.text, end='')
464
598
  ```
465
599
 
466
600
  #### Streaming for image content
@@ -470,35 +604,35 @@ you can use the `from_uri` class method to create a `Part` object.
470
604
 
471
605
  ```python
472
606
  for chunk in client.models.generate_content_stream(
473
- model="gemini-2.0-flash-exp",
607
+ model='gemini-2.0-flash-001',
474
608
  contents=[
475
- "What is this image about?",
609
+ 'What is this image about?',
476
610
  types.Part.from_uri(
477
- file_uri="gs://generativeai-downloads/images/scones.jpg",
478
- mime_type="image/jpeg",
611
+ file_uri='gs://generativeai-downloads/images/scones.jpg',
612
+ mime_type='image/jpeg',
479
613
  ),
480
614
  ],
481
615
  ):
482
- print(chunk.text, end="")
616
+ print(chunk.text, end='')
483
617
  ```
484
618
 
485
619
  If your image is stored in your local file system, you can read it in as bytes
486
620
  data and use the `from_bytes` class method to create a `Part` object.
487
621
 
488
622
  ```python
489
- YOUR_IMAGE_PATH = "your_image_path"
490
- YOUR_IMAGE_MIME_TYPE = "your_image_mime_type"
491
- with open(YOUR_IMAGE_PATH, "rb") as f:
623
+ YOUR_IMAGE_PATH = 'your_image_path'
624
+ YOUR_IMAGE_MIME_TYPE = 'your_image_mime_type'
625
+ with open(YOUR_IMAGE_PATH, 'rb') as f:
492
626
  image_bytes = f.read()
493
627
 
494
628
  for chunk in client.models.generate_content_stream(
495
- model="gemini-2.0-flash-exp",
629
+ model='gemini-2.0-flash-001',
496
630
  contents=[
497
- "What is this image about?",
631
+ 'What is this image about?',
498
632
  types.Part.from_bytes(data=image_bytes, mime_type=YOUR_IMAGE_MIME_TYPE),
499
633
  ],
500
634
  ):
501
- print(chunk.text, end="")
635
+ print(chunk.text, end='')
502
636
  ```
503
637
 
504
638
  ### Async
@@ -511,7 +645,7 @@ of `client.models.generate_content`
511
645
 
512
646
  ```python
513
647
  response = await client.aio.models.generate_content(
514
- model="gemini-2.0-flash-exp", contents="Tell me a story in 300 words."
648
+ model='gemini-2.0-flash-001', contents='Tell me a story in 300 words.'
515
649
  )
516
650
 
517
651
  print(response.text)
@@ -521,17 +655,17 @@ print(response.text)
521
655
 
522
656
  ```python
523
657
  async for chunk in await client.aio.models.generate_content_stream(
524
- model="gemini-2.0-flash-exp", contents="Tell me a story in 300 words."
658
+ model='gemini-2.0-flash-001', contents='Tell me a story in 300 words.'
525
659
  ):
526
- print(chunk.text, end="")
660
+ print(chunk.text, end='')
527
661
  ```
528
662
 
529
663
  ### Count Tokens and Compute Tokens
530
664
 
531
665
  ```python
532
666
  response = client.models.count_tokens(
533
- model="gemini-2.0-flash-exp",
534
- contents="why is the sky blue?",
667
+ model='gemini-2.0-flash-001',
668
+ contents='why is the sky blue?',
535
669
  )
536
670
  print(response)
537
671
  ```
@@ -542,8 +676,8 @@ Compute tokens is only supported in Vertex AI.
542
676
 
543
677
  ```python
544
678
  response = client.models.compute_tokens(
545
- model="gemini-2.0-flash-exp",
546
- contents="why is the sky blue?",
679
+ model='gemini-2.0-flash-001',
680
+ contents='why is the sky blue?',
547
681
  )
548
682
  print(response)
549
683
  ```
@@ -552,8 +686,8 @@ print(response)
552
686
 
553
687
  ```python
554
688
  response = await client.aio.models.count_tokens(
555
- model="gemini-2.0-flash-exp",
556
- contents="why is the sky blue?",
689
+ model='gemini-2.0-flash-001',
690
+ contents='why is the sky blue?',
557
691
  )
558
692
  print(response)
559
693
  ```
@@ -562,8 +696,8 @@ print(response)
562
696
 
563
697
  ```python
564
698
  response = client.models.embed_content(
565
- model="text-embedding-004",
566
- contents="why is the sky blue?",
699
+ model='text-embedding-004',
700
+ contents='why is the sky blue?',
567
701
  )
568
702
  print(response)
569
703
  ```
@@ -571,8 +705,8 @@ print(response)
571
705
  ```python
572
706
  # multiple contents with config
573
707
  response = client.models.embed_content(
574
- model="text-embedding-004",
575
- contents=["why is the sky blue?", "What is your age?"],
708
+ model='text-embedding-004',
709
+ contents=['why is the sky blue?', 'What is your age?'],
576
710
  config=types.EmbedContentConfig(output_dimensionality=10),
577
711
  )
578
712
 
@@ -588,13 +722,12 @@ Support for generate images in Gemini Developer API is behind an allowlist
588
722
  ```python
589
723
  # Generate Image
590
724
  response1 = client.models.generate_images(
591
- model="imagen-3.0-generate-002",
592
- prompt="An umbrella in the foreground, and a rainy night sky in the background",
725
+ model='imagen-3.0-generate-002',
726
+ prompt='An umbrella in the foreground, and a rainy night sky in the background',
593
727
  config=types.GenerateImagesConfig(
594
- negative_prompt="human",
595
728
  number_of_images=1,
596
729
  include_rai_reason=True,
597
- output_mime_type="image/jpeg",
730
+ output_mime_type='image/jpeg',
598
731
  ),
599
732
  )
600
733
  response1.generated_images[0].image.show()
@@ -607,12 +740,12 @@ Upscale image is only supported in Vertex AI.
607
740
  ```python
608
741
  # Upscale the generated image from above
609
742
  response2 = client.models.upscale_image(
610
- model="imagen-3.0-generate-001",
743
+ model='imagen-3.0-generate-001',
611
744
  image=response1.generated_images[0].image,
612
- upscale_factor="x2",
745
+ upscale_factor='x2',
613
746
  config=types.UpscaleImageConfig(
614
747
  include_rai_reason=True,
615
- output_mime_type="image/jpeg",
748
+ output_mime_type='image/jpeg',
616
749
  ),
617
750
  )
618
751
  response2.generated_images[0].image.show()
@@ -637,26 +770,53 @@ raw_ref_image = RawReferenceImage(
637
770
  mask_ref_image = MaskReferenceImage(
638
771
  reference_id=2,
639
772
  config=types.MaskReferenceConfig(
640
- mask_mode="MASK_MODE_BACKGROUND",
773
+ mask_mode='MASK_MODE_BACKGROUND',
641
774
  mask_dilation=0,
642
775
  ),
643
776
  )
644
777
 
645
778
  response3 = client.models.edit_image(
646
- model="imagen-3.0-capability-001",
647
- prompt="Sunlight and clear sky",
779
+ model='imagen-3.0-capability-001',
780
+ prompt='Sunlight and clear sky',
648
781
  reference_images=[raw_ref_image, mask_ref_image],
649
782
  config=types.EditImageConfig(
650
- edit_mode="EDIT_MODE_INPAINT_INSERTION",
783
+ edit_mode='EDIT_MODE_INPAINT_INSERTION',
651
784
  number_of_images=1,
652
- negative_prompt="human",
653
785
  include_rai_reason=True,
654
- output_mime_type="image/jpeg",
786
+ output_mime_type='image/jpeg',
655
787
  ),
656
788
  )
657
789
  response3.generated_images[0].image.show()
658
790
  ```
659
791
 
792
+ ### Veo
793
+
794
+ #### Generate Videos
795
+
796
+ Support for generate videos in Vertex and Gemini Developer API is behind an allowlist
797
+
798
+ ```python
799
+ # Create operation
800
+ operation = client.models.generate_videos(
801
+ model='veo-2.0-generate-001',
802
+ prompt='A neon hologram of a cat driving at top speed',
803
+ config=types.GenerateVideosConfig(
804
+ number_of_videos=1,
805
+ fps=24,
806
+ duration_seconds=5,
807
+ enhance_prompt=True,
808
+ ),
809
+ )
810
+
811
+ # Poll operation
812
+ while not operation.done:
813
+ time.sleep(20)
814
+ operation = client.operations.get(operation)
815
+
816
+ video = operation.result.generated_videos[0].video
817
+ video.show()
818
+ ```
819
+
660
820
  ## Chats
661
821
 
662
822
  Create a chat session to start a multi-turn conversations with the model.
@@ -664,32 +824,32 @@ Create a chat session to start a multi-turn conversations with the model.
664
824
  ### Send Message
665
825
 
666
826
  ```python
667
- chat = client.chats.create(model="gemini-2.0-flash-exp")
668
- response = chat.send_message("tell me a story")
827
+ chat = client.chats.create(model='gemini-2.0-flash-001')
828
+ response = chat.send_message('tell me a story')
669
829
  print(response.text)
670
830
  ```
671
831
 
672
832
  ### Streaming
673
833
 
674
834
  ```python
675
- chat = client.chats.create(model="gemini-2.0-flash-exp")
676
- for chunk in chat.send_message_stream("tell me a story"):
835
+ chat = client.chats.create(model='gemini-2.0-flash-001')
836
+ for chunk in chat.send_message_stream('tell me a story'):
677
837
  print(chunk.text)
678
838
  ```
679
839
 
680
840
  ### Async
681
841
 
682
842
  ```python
683
- chat = client.aio.chats.create(model="gemini-2.0-flash-exp")
684
- response = await chat.send_message("tell me a story")
843
+ chat = client.aio.chats.create(model='gemini-2.0-flash-001')
844
+ response = await chat.send_message('tell me a story')
685
845
  print(response.text)
686
846
  ```
687
847
 
688
848
  ### Async Streaming
689
849
 
690
850
  ```python
691
- chat = client.aio.chats.create(model="gemini-2.0-flash-exp")
692
- async for chunk in await chat.send_message_stream("tell me a story"):
851
+ chat = client.aio.chats.create(model='gemini-2.0-flash-001')
852
+ async for chunk in await chat.send_message_stream('tell me a story'):
693
853
  print(chunk.text)
694
854
  ```
695
855
 
@@ -705,17 +865,24 @@ Files are only supported in Gemini Developer API.
705
865
  ### Upload
706
866
 
707
867
  ```python
708
- file1 = client.files.upload(path="2312.11805v3.pdf")
709
- file2 = client.files.upload(path="2403.05530.pdf")
868
+ file1 = client.files.upload(file='2312.11805v3.pdf')
869
+ file2 = client.files.upload(file='2403.05530.pdf')
710
870
 
711
871
  print(file1)
712
872
  print(file2)
713
873
  ```
714
874
 
875
+ ### Get
876
+
877
+ ```python
878
+ file1 = client.files.upload(file='2312.11805v3.pdf')
879
+ file_info = client.files.get(name=file1.name)
880
+ ```
881
+
715
882
  ### Delete
716
883
 
717
884
  ```python
718
- file3 = client.files.upload(path="2312.11805v3.pdf")
885
+ file3 = client.files.upload(file='2312.11805v3.pdf')
719
886
 
720
887
  client.files.delete(name=file3.name)
721
888
  ```
@@ -729,32 +896,32 @@ client.files.delete(name=file3.name)
729
896
  ```python
730
897
  if client.vertexai:
731
898
  file_uris = [
732
- "gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf",
733
- "gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf",
899
+ 'gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf',
900
+ 'gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf',
734
901
  ]
735
902
  else:
736
903
  file_uris = [file1.uri, file2.uri]
737
904
 
738
905
  cached_content = client.caches.create(
739
- model="gemini-1.5-pro-002",
906
+ model='gemini-1.5-pro-002',
740
907
  config=types.CreateCachedContentConfig(
741
908
  contents=[
742
909
  types.Content(
743
- role="user",
910
+ role='user',
744
911
  parts=[
745
912
  types.Part.from_uri(
746
- file_uri=file_uris[0], mime_type="application/pdf"
913
+ file_uri=file_uris[0], mime_type='application/pdf'
747
914
  ),
748
915
  types.Part.from_uri(
749
916
  file_uri=file_uris[1],
750
- mime_type="application/pdf",
917
+ mime_type='application/pdf',
751
918
  ),
752
919
  ],
753
920
  )
754
921
  ],
755
- system_instruction="What is the sum of the two pdfs?",
756
- display_name="test cache",
757
- ttl="3600s",
922
+ system_instruction='What is the sum of the two pdfs?',
923
+ display_name='test cache',
924
+ ttl='3600s',
758
925
  ),
759
926
  )
760
927
  ```
@@ -769,8 +936,8 @@ cached_content = client.caches.get(name=cached_content.name)
769
936
 
770
937
  ```python
771
938
  response = client.models.generate_content(
772
- model="gemini-1.5-pro-002",
773
- contents="Summarize the pdfs",
939
+ model='gemini-1.5-pro-002',
940
+ contents='Summarize the pdfs',
774
941
  config=types.GenerateContentConfig(
775
942
  cached_content=cached_content.name,
776
943
  ),
@@ -790,17 +957,17 @@ tuning through `tune`.
790
957
 
791
958
  ```python
792
959
  if client.vertexai:
793
- model = "gemini-1.5-pro-002"
960
+ model = 'gemini-1.5-pro-002'
794
961
  training_dataset = types.TuningDataset(
795
- gcs_uri="gs://cloud-samples-data/ai-platform/generative_ai/gemini-1_5/text/sft_train_data.jsonl",
962
+ gcs_uri='gs://cloud-samples-data/ai-platform/generative_ai/gemini-1_5/text/sft_train_data.jsonl',
796
963
  )
797
964
  else:
798
- model = "models/gemini-1.0-pro-001"
965
+ model = 'models/gemini-1.0-pro-001'
799
966
  training_dataset = types.TuningDataset(
800
967
  examples=[
801
968
  types.TuningExample(
802
- text_input=f"Input text {i}",
803
- output=f"Output text {i}",
969
+ text_input=f'Input text {i}',
970
+ output=f'Output text {i}',
804
971
  )
805
972
  for i in range(5)
806
973
  ],
@@ -812,7 +979,7 @@ tuning_job = client.tunings.tune(
812
979
  base_model=model,
813
980
  training_dataset=training_dataset,
814
981
  config=types.CreateTuningJobConfig(
815
- epoch_count=1, tuned_model_display_name="test_dataset_examples model"
982
+ epoch_count=1, tuned_model_display_name='test_dataset_examples model'
816
983
  ),
817
984
  )
818
985
  print(tuning_job)
@@ -830,8 +997,8 @@ import time
830
997
 
831
998
  running_states = set(
832
999
  [
833
- "JOB_STATE_PENDING",
834
- "JOB_STATE_RUNNING",
1000
+ 'JOB_STATE_PENDING',
1001
+ 'JOB_STATE_RUNNING',
835
1002
  ]
836
1003
  )
837
1004
 
@@ -846,7 +1013,7 @@ while tuning_job.state in running_states:
846
1013
  ```python
847
1014
  response = client.models.generate_content(
848
1015
  model=tuning_job.tuned_model.endpoint,
849
- contents="why is the sky blue?",
1016
+ contents='why is the sky blue?',
850
1017
  )
851
1018
 
852
1019
  print(response.text)
@@ -864,12 +1031,12 @@ print(tuned_model)
864
1031
  To retrieve base models, see [list base models](#list-base-models).
865
1032
 
866
1033
  ```python
867
- for model in client.models.list(config={"page_size": 10}):
1034
+ for model in client.models.list(config={'page_size': 10, 'query_base': False}):
868
1035
  print(model)
869
1036
  ```
870
1037
 
871
1038
  ```python
872
- pager = client.models.list(config={"page_size": 10})
1039
+ pager = client.models.list(config={'page_size': 10, 'query_base': False})
873
1040
  print(pager.page_size)
874
1041
  print(pager[0])
875
1042
  pager.next_page()
@@ -879,12 +1046,12 @@ print(pager[0])
879
1046
  #### Async
880
1047
 
881
1048
  ```python
882
- async for job in await client.aio.models.list(config={"page_size": 10}):
1049
+ async for job in await client.aio.models.list(config={'page_size': 10, 'query_base': False}):
883
1050
  print(job)
884
1051
  ```
885
1052
 
886
1053
  ```python
887
- async_pager = await client.aio.models.list(config={"page_size": 10})
1054
+ async_pager = await client.aio.models.list(config={'page_size': 10, 'query_base': False})
888
1055
  print(async_pager.page_size)
889
1056
  print(async_pager[0])
890
1057
  await async_pager.next_page()
@@ -899,7 +1066,7 @@ model = pager[0]
899
1066
  model = client.models.update(
900
1067
  model=model.name,
901
1068
  config=types.UpdateModelConfig(
902
- display_name="my tuned model", description="my tuned model description"
1069
+ display_name='my tuned model', description='my tuned model description'
903
1070
  ),
904
1071
  )
905
1072
 
@@ -910,12 +1077,12 @@ print(model)
910
1077
  ### List Tuning Jobs
911
1078
 
912
1079
  ```python
913
- for job in client.tunings.list(config={"page_size": 10}):
1080
+ for job in client.tunings.list(config={'page_size': 10}):
914
1081
  print(job)
915
1082
  ```
916
1083
 
917
1084
  ```python
918
- pager = client.tunings.list(config={"page_size": 10})
1085
+ pager = client.tunings.list(config={'page_size': 10})
919
1086
  print(pager.page_size)
920
1087
  print(pager[0])
921
1088
  pager.next_page()
@@ -925,12 +1092,12 @@ print(pager[0])
925
1092
  #### Async
926
1093
 
927
1094
  ```python
928
- async for job in await client.aio.tunings.list(config={"page_size": 10}):
1095
+ async for job in await client.aio.tunings.list(config={'page_size': 10}):
929
1096
  print(job)
930
1097
  ```
931
1098
 
932
1099
  ```python
933
- async_pager = await client.aio.tunings.list(config={"page_size": 10})
1100
+ async_pager = await client.aio.tunings.list(config={'page_size': 10})
934
1101
  print(async_pager.page_size)
935
1102
  print(async_pager[0])
936
1103
  await async_pager.next_page()
@@ -946,8 +1113,8 @@ Only supported in Vertex AI.
946
1113
  ```python
947
1114
  # Specify model and source file only, destination and job display name will be auto-populated
948
1115
  job = client.batches.create(
949
- model="gemini-1.5-flash-002",
950
- src="bq://my-project.my-dataset.my-table",
1116
+ model='gemini-1.5-flash-002',
1117
+ src='bq://my-project.my-dataset.my-table',
951
1118
  )
952
1119
 
953
1120
  job
@@ -963,10 +1130,10 @@ job.state
963
1130
  ```python
964
1131
  completed_states = set(
965
1132
  [
966
- "JOB_STATE_SUCCEEDED",
967
- "JOB_STATE_FAILED",
968
- "JOB_STATE_CANCELLED",
969
- "JOB_STATE_PAUSED",
1133
+ 'JOB_STATE_SUCCEEDED',
1134
+ 'JOB_STATE_FAILED',
1135
+ 'JOB_STATE_CANCELLED',
1136
+ 'JOB_STATE_PAUSED',
970
1137
  ]
971
1138
  )
972
1139
 
@@ -1020,3 +1187,20 @@ delete_job = client.batches.delete(name=job.name)
1020
1187
 
1021
1188
  delete_job
1022
1189
  ```
1190
+
1191
+ ## Error Handling
1192
+
1193
+ To handle errors raised by the model service, the SDK provides this [APIError](https://github.com/googleapis/python-genai/blob/main/google/genai/errors.py) class.
1194
+
1195
+ ```python
1196
+ from google.genai import errors
1197
+
1198
+ try:
1199
+ client.models.generate_content(
1200
+ model="invalid-model-name",
1201
+ contents="What is your name?",
1202
+ )
1203
+ except errors.APIError as e:
1204
+ print(e.code) # 404
1205
+ print(e.message)
1206
+ ```