google-genai 1.60.0__py3-none-any.whl → 1.62.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.
Files changed (34) hide show
  1. google/genai/_interactions/_base_client.py +5 -2
  2. google/genai/_interactions/_compat.py +3 -3
  3. google/genai/_interactions/_utils/_json.py +50 -0
  4. google/genai/_interactions/resources/interactions.py +50 -28
  5. google/genai/_interactions/types/__init__.py +2 -1
  6. google/genai/_interactions/types/content_delta.py +1 -1
  7. google/genai/_interactions/types/function_result_content.py +2 -1
  8. google/genai/_interactions/types/function_result_content_param.py +4 -4
  9. google/genai/_interactions/types/{interaction_event.py → interaction_complete_event.py} +3 -3
  10. google/genai/_interactions/types/interaction_create_params.py +4 -4
  11. google/genai/_interactions/types/interaction_get_params.py +3 -0
  12. google/genai/_interactions/types/interaction_sse_event.py +11 -2
  13. google/genai/_interactions/types/interaction_start_event.py +36 -0
  14. google/genai/batches.py +3 -0
  15. google/genai/errors.py +19 -6
  16. google/genai/files.py +15 -15
  17. google/genai/live.py +22 -2
  18. google/genai/live_music.py +14 -1
  19. google/genai/models.py +486 -197
  20. google/genai/tests/batches/test_create_with_inlined_requests.py +31 -15
  21. google/genai/tests/batches/test_get.py +1 -1
  22. google/genai/tests/client/test_client_close.py +0 -1
  23. google/genai/tests/errors/test_api_error.py +38 -0
  24. google/genai/tests/files/test_register_table.py +1 -1
  25. google/genai/tests/transformers/test_schema.py +10 -1
  26. google/genai/tests/tunings/test_tune.py +87 -0
  27. google/genai/tunings.py +211 -20
  28. google/genai/types.py +178 -14
  29. google/genai/version.py +1 -1
  30. {google_genai-1.60.0.dist-info → google_genai-1.62.0.dist-info}/METADATA +1 -1
  31. {google_genai-1.60.0.dist-info → google_genai-1.62.0.dist-info}/RECORD +34 -32
  32. {google_genai-1.60.0.dist-info → google_genai-1.62.0.dist-info}/WHEEL +1 -1
  33. {google_genai-1.60.0.dist-info → google_genai-1.62.0.dist-info}/licenses/LICENSE +0 -0
  34. {google_genai-1.60.0.dist-info → google_genai-1.62.0.dist-info}/top_level.txt +0 -0
@@ -42,20 +42,36 @@ _SAFETY_SETTINGS = [
42
42
  },
43
43
  ]
44
44
 
45
- _INLINED_REQUEST = {
46
- 'contents': [{
47
- 'parts': [{
48
- 'text': 'Hello!',
45
+ _INLINED_REQUESTS = [
46
+ {
47
+ 'contents': [{
48
+ 'parts': [{
49
+ 'text': 'what is the number after 1? return just the number.',
50
+ }],
51
+ 'role': 'user',
49
52
  }],
50
- 'role': 'user',
51
- }],
52
- 'metadata': {
53
- 'key': 'request-1',
53
+ 'metadata': {
54
+ 'key': 'request-1',
55
+ },
56
+ 'config': {
57
+ 'safety_settings': _SAFETY_SETTINGS,
58
+ },
54
59
  },
55
- 'config': {
56
- 'safety_settings': _SAFETY_SETTINGS,
60
+ {
61
+ 'contents': [{
62
+ 'parts': [{
63
+ 'text': 'what is the number after 2? return just the number.',
64
+ }],
65
+ 'role': 'user',
66
+ }],
67
+ 'metadata': {
68
+ 'key': 'request-2',
69
+ },
70
+ 'config': {
71
+ 'safety_settings': _SAFETY_SETTINGS,
72
+ },
57
73
  },
58
- }
74
+ ]
59
75
  _INLINED_TEXT_REQUEST_UNION = {
60
76
  'contents': [{
61
77
  'parts': [{
@@ -154,7 +170,7 @@ test_table: list[pytest_helper.TestTableItem] = [
154
170
  name='test_union_with_inlined_request',
155
171
  parameters=types._CreateBatchJobParameters(
156
172
  model=_MLDEV_GEMINI_MODEL,
157
- src=[_INLINED_REQUEST],
173
+ src=_INLINED_REQUESTS,
158
174
  config={
159
175
  'display_name': _DISPLAY_NAME,
160
176
  },
@@ -166,7 +182,7 @@ test_table: list[pytest_helper.TestTableItem] = [
166
182
  name='test_with_inlined_request',
167
183
  parameters=types._CreateBatchJobParameters(
168
184
  model=_MLDEV_GEMINI_MODEL,
169
- src={'inlined_requests': [_INLINED_REQUEST]},
185
+ src={'inlined_requests': _INLINED_REQUESTS},
170
186
  config={
171
187
  'display_name': _DISPLAY_NAME,
172
188
  },
@@ -177,7 +193,7 @@ test_table: list[pytest_helper.TestTableItem] = [
177
193
  name='test_with_inlined_request_config',
178
194
  parameters=types._CreateBatchJobParameters(
179
195
  model=_MLDEV_GEMINI_MODEL,
180
- src={'inlined_requests': [_INLINED_TEXT_REQUEST]},
196
+ src={'inlined_requests': _INLINED_REQUESTS},
181
197
  config={
182
198
  'display_name': _DISPLAY_NAME,
183
199
  },
@@ -247,7 +263,7 @@ async def test_async_create(client):
247
263
  with pytest_helper.exception_if_vertex(client, ValueError):
248
264
  batch_job = await client.aio.batches.create(
249
265
  model=_GEMINI_MODEL,
250
- src=[_INLINED_REQUEST],
266
+ src=_INLINED_REQUESTS,
251
267
  )
252
268
  assert batch_job.name.startswith('batches/')
253
269
  assert (
@@ -29,7 +29,7 @@ _BATCH_JOB_FULL_RESOURCE_NAME = (
29
29
  f'batchPredictionJobs/{_BATCH_JOB_NAME}'
30
30
  )
31
31
  # MLDev batch operation name.
32
- _MLDEV_BATCH_OPERATION_NAME = 'batches/0yew7plxupyybd7appsrq5vw7w0lp3l79lab'
32
+ _MLDEV_BATCH_OPERATION_NAME = 'batches/z2p8ksus4lyxt25rntl3fpd67p2niw4hfij5'
33
33
  _INVALID_BATCH_JOB_NAME = 'invalid_name'
34
34
 
35
35
 
@@ -90,7 +90,6 @@ async def test_async_httpx_client_context_manager():
90
90
  assert async_client._api_client._async_httpx_client.is_closed
91
91
 
92
92
 
93
- @requires_aiohttp
94
93
  @pytest.fixture
95
94
  def mock_request():
96
95
  mock_aiohttp_response = mock.Mock(spec=aiohttp.ClientSession.request)
@@ -23,6 +23,7 @@ import pickle
23
23
 
24
24
  import httpx
25
25
  import pytest
26
+ import websockets
26
27
 
27
28
  from ... import errors
28
29
 
@@ -257,6 +258,43 @@ def test_constructor_message_not_present():
257
258
  }
258
259
 
259
260
 
261
+ def test_constructor_with_websocket_connection_closed_error():
262
+ actual_error = errors.APIError(
263
+ 1007,
264
+ 'At most one response modality can be specified in the setup request.'
265
+ ' To enable simultaneous transcription and audio output,',
266
+ None,
267
+ )
268
+ assert actual_error.code == 1007
269
+ assert (
270
+ actual_error.details
271
+ == 'At most one response modality can be specified in the setup request.'
272
+ ' To enable simultaneous transcription and audio output,',
273
+ )
274
+ assert actual_error.status == None
275
+ assert actual_error.message == None
276
+
277
+
278
+ def test_raise_for_websocket_connection_closed_error():
279
+ try:
280
+ errors.APIError.raise_error(
281
+ 1007,
282
+ 'At most one response modality can be specified in the setup request.'
283
+ ' To enable simultaneous transcription and audio output,',
284
+ None,
285
+ )
286
+ except errors.APIError as actual_error:
287
+ assert actual_error.code == 1007
288
+ assert (
289
+ actual_error.details
290
+ == 'At most one response modality can be specified in the setup'
291
+ ' request.'
292
+ ' To enable simultaneous transcription and audio output,'
293
+ )
294
+ assert actual_error.status == None
295
+ assert actual_error.message == None
296
+
297
+
260
298
  def test_raise_for_response_code_exist_json_decoder_error():
261
299
  class FakeResponse(httpx.Response):
262
300
 
@@ -42,7 +42,7 @@ def get_headers():
42
42
  test_table: list[pytest_helper.TestTableItem] = [
43
43
  pytest_helper.TestTableItem(
44
44
  name='test_register',
45
- parameters=types._RegisterFilesParameters(uris=['gs://unified-genai-dev/image.jpg']),
45
+ parameters=types._InternalRegisterFilesParameters(uris=['gs://unified-genai-dev/image.jpg']),
46
46
  exception_if_vertex='only supported in the Gemini Developer client',
47
47
  skip_in_api_mode=(
48
48
  'The files have a TTL, they cannot be reliably retrieved for a long'
@@ -79,7 +79,6 @@ class CountryInfoWithAnyOf(pydantic.BaseModel):
79
79
 
80
80
 
81
81
  @pytest.fixture
82
- @pytest.mark.parametrize('use_vertex', [True, False])
83
82
  def client(use_vertex):
84
83
  if use_vertex:
85
84
  yield google_genai_client_module.Client(
@@ -91,6 +90,7 @@ def client(use_vertex):
91
90
  )
92
91
 
93
92
 
93
+ @pytest.mark.parametrize('use_vertex', [True, False])
94
94
  def test_build_schema_for_list_of_pydantic_schema(client):
95
95
  """Tests _build_schema() when list[pydantic.BaseModel] is provided to response_schema."""
96
96
 
@@ -112,6 +112,7 @@ def test_build_schema_for_list_of_pydantic_schema(client):
112
112
  assert list_schema['required'] == list(country_info_fields.keys())
113
113
 
114
114
 
115
+ @pytest.mark.parametrize('use_vertex', [True, False])
115
116
  def test_build_schema_for_list_of_nested_pydantic_schema(client):
116
117
  """Tests _build_schema() when list[pydantic.BaseModel] is provided to response_schema and the pydantic.BaseModel has nested pydantic fields."""
117
118
  list_schema = _transformers.t_schema(
@@ -132,6 +133,7 @@ def test_build_schema_for_list_of_nested_pydantic_schema(client):
132
133
  assert field_name in currency_info_fields
133
134
 
134
135
 
136
+ @pytest.mark.parametrize('use_vertex', [True, False])
135
137
  def test_t_schema_for_pydantic_schema(client):
136
138
  """Tests t_schema when pydantic.BaseModel is passed to response_schema."""
137
139
  transformed_schema = _transformers.t_schema(client, CountryInfo)
@@ -143,6 +145,7 @@ def test_t_schema_for_pydantic_schema(client):
143
145
  )
144
146
 
145
147
 
148
+ @pytest.mark.parametrize('use_vertex', [True, False])
146
149
  def test_t_schema_for_list_of_pydantic_schema(client):
147
150
  """Tests t_schema when list[pydantic.BaseModel] is passed to response_schema."""
148
151
  transformed_schema = _transformers.t_schema(client, list[CountryInfo])
@@ -156,6 +159,7 @@ def test_t_schema_for_list_of_pydantic_schema(client):
156
159
  )
157
160
 
158
161
 
162
+ @pytest.mark.parametrize('use_vertex', [True, False])
159
163
  def test_t_schema_for_null_fields(client):
160
164
  """Tests t_schema when null fields are present."""
161
165
  transformed_schema = _transformers.t_schema(client, CountryInfoWithNullFields)
@@ -163,6 +167,7 @@ def test_t_schema_for_null_fields(client):
163
167
  assert transformed_schema.properties['population'].nullable
164
168
 
165
169
 
170
+ #@pytest.mark.parametrize('use_vertex', [True, False])
166
171
  def test_schema_with_no_null_fields_is_unchanged():
167
172
  """Tests handle_null_fields() doesn't change anything when no null fields are present."""
168
173
  test_properties = {
@@ -207,6 +212,7 @@ def test_schema_with_default_value(client):
207
212
  assert transformed_schema == expected_schema
208
213
 
209
214
 
215
+ @pytest.mark.parametrize('use_vertex', [True, False])
210
216
  def test_schema_with_any_of(client):
211
217
  transformed_schema = _transformers.t_schema(client, CountryInfoWithAnyOf)
212
218
  expected_schema = types.Schema(
@@ -601,6 +607,7 @@ def test_process_schema_order_properties_propagates_into_any_of(
601
607
  assert schema == schema_without_property_ordering
602
608
 
603
609
 
610
+ @pytest.mark.parametrize('use_vertex', [True, False])
604
611
  def test_t_schema_does_not_change_property_ordering_if_set(client):
605
612
  """Tests t_schema doesn't overwrite the property_ordering field if already set."""
606
613
 
@@ -612,6 +619,7 @@ def test_t_schema_does_not_change_property_ordering_if_set(client):
612
619
  assert transformed_schema.property_ordering == custom_property_ordering
613
620
 
614
621
 
622
+ @pytest.mark.parametrize('use_vertex', [True, False])
615
623
  def test_t_schema_sets_property_ordering_for_json_schema(client):
616
624
  """Tests t_schema sets the property_ordering field for json schemas."""
617
625
 
@@ -629,6 +637,7 @@ def test_t_schema_sets_property_ordering_for_json_schema(client):
629
637
  ]
630
638
 
631
639
 
640
+ @pytest.mark.parametrize('use_vertex', [True, False])
632
641
  def test_t_schema_sets_property_ordering_for_schema_type(client):
633
642
  """Tests t_schema sets the property_ordering field for Schema types."""
634
643
 
@@ -20,6 +20,12 @@ from ... import types as genai_types
20
20
  from .. import pytest_helper
21
21
  import pytest
22
22
 
23
+
24
+ VERTEX_HTTP_OPTIONS = {
25
+ 'api_version': 'v1beta1',
26
+ 'base_url': 'https://us-central1-autopush-aiplatform.sandbox.googleapis.com/',
27
+ }
28
+
23
29
  evaluation_config=genai_types.EvaluationConfig(
24
30
  metrics=[
25
31
  genai_types.Metric(name="bleu", prompt_template="test prompt template")
@@ -158,6 +164,87 @@ test_table: list[pytest_helper.TestTableItem] = [
158
164
  ),
159
165
  exception_if_mldev="vertex_dataset_resource parameter is not supported in Gemini API.",
160
166
  ),
167
+ pytest_helper.TestTableItem(
168
+ name="test_tune_distillation",
169
+ parameters=genai_types.CreateTuningJobParameters(
170
+ base_model="meta/llama3_1@llama-3.1-8b-instruct",
171
+ training_dataset=genai_types.TuningDataset(
172
+ gcs_uri="gs://nathreya-oss-tuning-sdk-test/distillation-openai-opposites.jsonl",
173
+ ),
174
+ config=genai_types.CreateTuningJobConfig(
175
+ method="DISTILLATION",
176
+ base_teacher_model="deepseek-ai/deepseek-v3.1-maas",
177
+ epoch_count=20,
178
+ validation_dataset=genai_types.TuningValidationDataset(
179
+ gcs_uri="gs://nathreya-oss-tuning-sdk-test/distillation-val-openai-opposites.jsonl",
180
+ ),
181
+ output_uri="gs://nathreya-oss-tuning-sdk-test/ayushagra-distillation-test-folder",
182
+ http_options=VERTEX_HTTP_OPTIONS,
183
+ ),
184
+ ),
185
+ exception_if_mldev="parameter is not supported in Gemini API.",
186
+ ),
187
+ pytest_helper.TestTableItem(
188
+ name="test_tune_oss_sft",
189
+ parameters=genai_types.CreateTuningJobParameters(
190
+ base_model="meta/llama3_1@llama-3.1-8b-instruct",
191
+ training_dataset=genai_types.TuningDataset(
192
+ gcs_uri="gs://nathreya-oss-tuning-sdk-test/distillation-openai-opposites.jsonl",
193
+ ),
194
+ config=genai_types.CreateTuningJobConfig(
195
+ epoch_count=20,
196
+ validation_dataset=genai_types.TuningValidationDataset(
197
+ gcs_uri="gs://nathreya-oss-tuning-sdk-test/distillation-val-openai-opposites.jsonl",
198
+ ),
199
+ custom_base_model="gs://nathreya-oss-tuning-sdk-test/ayushagra-distillation-test-folder/postprocess/node-0/checkpoints/final",
200
+ output_uri="gs://nathreya-oss-tuning-sdk-test/ayushagra-distillation-test",
201
+ http_options=VERTEX_HTTP_OPTIONS,
202
+ ),
203
+ ),
204
+ exception_if_mldev="not supported in Gemini API",
205
+ ),
206
+ pytest_helper.TestTableItem(
207
+ name="test_tune_oss_sft_hyperparams",
208
+ parameters=genai_types.CreateTuningJobParameters(
209
+ base_model="meta/llama3_1@llama-3.1-8b-instruct",
210
+ training_dataset=genai_types.TuningDataset(
211
+ gcs_uri="gs://nathreya-oss-tuning-sdk-test/distillation-openai-opposites.jsonl",
212
+ ),
213
+ config=genai_types.CreateTuningJobConfig(
214
+ epoch_count=20,
215
+ validation_dataset=genai_types.TuningValidationDataset(
216
+ gcs_uri="gs://nathreya-oss-tuning-sdk-test/distillation-val-openai-opposites.jsonl",
217
+ ),
218
+ learning_rate=2.5e-4,
219
+ tuning_mode="TUNING_MODE_FULL",
220
+ custom_base_model="gs://nathreya-oss-tuning-sdk-test/ayushagra-distillation-test-folder/postprocess/node-0/checkpoints/final",
221
+ output_uri="gs://nathreya-oss-tuning-sdk-test/ayushagra-distillation-test",
222
+ http_options=VERTEX_HTTP_OPTIONS,
223
+ ),
224
+ ),
225
+ exception_if_mldev="not supported in Gemini API",
226
+ ),
227
+ pytest_helper.TestTableItem(
228
+ name="test_tune_oss_distillation",
229
+ parameters=genai_types.CreateTuningJobParameters(
230
+ base_model="meta/llama3_1@llama-3.1-8b-instruct",
231
+ training_dataset=genai_types.TuningDataset(
232
+ gcs_uri="gs://nathreya-oss-tuning-sdk-test/distillation-openai-opposites.jsonl",
233
+ ),
234
+ config=genai_types.CreateTuningJobConfig(
235
+ method="DISTILLATION",
236
+ base_teacher_model="deepseek-ai/deepseek-v3.1-maas",
237
+ epoch_count=20,
238
+ validation_dataset=genai_types.TuningValidationDataset(
239
+ gcs_uri="gs://nathreya-oss-tuning-sdk-test/distillation-val-openai-opposites.jsonl",
240
+ ),
241
+ custom_base_model="gs://nathreya-oss-tuning-sdk-test/ayushagra-distillation-test-folder/postprocess/node-0/checkpoints/final",
242
+ output_uri="gs://nathreya-oss-tuning-sdk-test/ayushagra-distillation-test",
243
+ http_options=VERTEX_HTTP_OPTIONS,
244
+ ),
245
+ ),
246
+ exception_if_mldev="not supported in Gemini API",
247
+ ),
161
248
  ]
162
249
 
163
250
  pytestmark = pytest_helper.setup(