google-genai 1.17.0__tar.gz → 1.18.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.
- {google_genai-1.17.0/google_genai.egg-info → google_genai-1.18.0}/PKG-INFO +1 -1
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/__init__.py +1 -2
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_api_client.py +10 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_common.py +36 -1
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_live_converters.py +28 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_tokens_converters.py +21 -7
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_transformers.py +2 -1
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/caches.py +14 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/chats.py +6 -3
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/live.py +18 -102
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/models.py +35 -3
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/types.py +17 -8
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/version.py +1 -1
- {google_genai-1.17.0 → google_genai-1.18.0/google_genai.egg-info}/PKG-INFO +1 -1
- {google_genai-1.17.0 → google_genai-1.18.0}/pyproject.toml +1 -1
- {google_genai-1.17.0 → google_genai-1.18.0}/LICENSE +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/MANIFEST.in +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/README.md +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_adapters.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_api_module.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_automatic_function_calling_util.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_base_url.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_extra_utils.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_mcp_utils.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_replay_api_client.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_test_api_client.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/batches.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/client.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/errors.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/files.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/live_music.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/operations.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/pagers.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/py.typed +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/tokens.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google/genai/tunings.py +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google_genai.egg-info/SOURCES.txt +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google_genai.egg-info/dependency_links.txt +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google_genai.egg-info/requires.txt +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/google_genai.egg-info/top_level.txt +0 -0
- {google_genai-1.17.0 → google_genai-1.18.0}/setup.cfg +0 -0
@@ -63,6 +63,11 @@ MAX_RETRY_COUNT = 3
|
|
63
63
|
INITIAL_RETRY_DELAY = 1 # second
|
64
64
|
DELAY_MULTIPLIER = 2
|
65
65
|
|
66
|
+
|
67
|
+
class EphemeralTokenAPIKeyError(ValueError):
|
68
|
+
"""Error raised when the API key is invalid."""
|
69
|
+
|
70
|
+
|
66
71
|
def _append_library_version_headers(headers: dict[str, str]) -> None:
|
67
72
|
"""Appends the telemetry header to the headers dict."""
|
68
73
|
library_label = f'google-genai-sdk/{version.__version__}'
|
@@ -625,6 +630,11 @@ class BaseApiClient:
|
|
625
630
|
versioned_path,
|
626
631
|
)
|
627
632
|
|
633
|
+
if self.api_key and self.api_key.startswith('auth_tokens/'):
|
634
|
+
raise EphemeralTokenAPIKeyError(
|
635
|
+
'Ephemeral tokens can only be used with the live API.'
|
636
|
+
)
|
637
|
+
|
628
638
|
timeout_in_seconds = _get_timeout_in_seconds(patched_http_options.timeout)
|
629
639
|
|
630
640
|
if patched_http_options.headers is None:
|
@@ -20,7 +20,7 @@ import datetime
|
|
20
20
|
import enum
|
21
21
|
import functools
|
22
22
|
import typing
|
23
|
-
from typing import Any, Callable, Optional, Union
|
23
|
+
from typing import Any, Callable, Optional, Union, get_origin, get_args
|
24
24
|
import uuid
|
25
25
|
import warnings
|
26
26
|
|
@@ -154,6 +154,38 @@ def convert_to_dict(obj: object) -> Any:
|
|
154
154
|
return obj
|
155
155
|
|
156
156
|
|
157
|
+
def _is_struct_type(annotation: type) -> bool:
|
158
|
+
"""Checks if the given annotation is list[dict[str, typing.Any]]
|
159
|
+
or typing.List[typing.Dict[str, typing.Any]].
|
160
|
+
|
161
|
+
This maps to Struct type in the API.
|
162
|
+
"""
|
163
|
+
outer_origin = get_origin(annotation)
|
164
|
+
outer_args = get_args(annotation)
|
165
|
+
|
166
|
+
if outer_origin is not list: # Python 3.9+ normalizes list
|
167
|
+
return False
|
168
|
+
|
169
|
+
if not outer_args or len(outer_args) != 1:
|
170
|
+
return False
|
171
|
+
|
172
|
+
inner_annotation = outer_args[0]
|
173
|
+
|
174
|
+
inner_origin = get_origin(inner_annotation)
|
175
|
+
inner_args = get_args(inner_annotation)
|
176
|
+
|
177
|
+
if inner_origin is not dict: # Python 3.9+ normalizes to dict
|
178
|
+
return False
|
179
|
+
|
180
|
+
if not inner_args or len(inner_args) != 2:
|
181
|
+
# dict should have exactly two type arguments
|
182
|
+
return False
|
183
|
+
|
184
|
+
# Check if the dict arguments are str and typing.Any
|
185
|
+
key_type, value_type = inner_args
|
186
|
+
return key_type is str and value_type is typing.Any
|
187
|
+
|
188
|
+
|
157
189
|
def _remove_extra_fields(
|
158
190
|
model: Any, response: dict[str, object]
|
159
191
|
) -> None:
|
@@ -188,6 +220,9 @@ def _remove_extra_fields(
|
|
188
220
|
if isinstance(value, dict) and typing.get_origin(annotation) is not dict:
|
189
221
|
_remove_extra_fields(annotation, value)
|
190
222
|
elif isinstance(value, list):
|
223
|
+
if _is_struct_type(annotation):
|
224
|
+
continue
|
225
|
+
|
191
226
|
for item in value:
|
192
227
|
# assume a list of dict is list of BaseModel
|
193
228
|
if isinstance(item, dict):
|
@@ -353,6 +353,13 @@ def _Part_to_mldev(
|
|
353
353
|
),
|
354
354
|
)
|
355
355
|
|
356
|
+
if getv(from_object, ['thought_signature']) is not None:
|
357
|
+
setv(
|
358
|
+
to_object,
|
359
|
+
['thoughtSignature'],
|
360
|
+
getv(from_object, ['thought_signature']),
|
361
|
+
)
|
362
|
+
|
356
363
|
if getv(from_object, ['code_execution_result']) is not None:
|
357
364
|
setv(
|
358
365
|
to_object,
|
@@ -415,6 +422,13 @@ def _Part_to_vertex(
|
|
415
422
|
),
|
416
423
|
)
|
417
424
|
|
425
|
+
if getv(from_object, ['thought_signature']) is not None:
|
426
|
+
setv(
|
427
|
+
to_object,
|
428
|
+
['thoughtSignature'],
|
429
|
+
getv(from_object, ['thought_signature']),
|
430
|
+
)
|
431
|
+
|
418
432
|
if getv(from_object, ['code_execution_result']) is not None:
|
419
433
|
setv(
|
420
434
|
to_object,
|
@@ -2759,6 +2773,13 @@ def _Part_from_mldev(
|
|
2759
2773
|
),
|
2760
2774
|
)
|
2761
2775
|
|
2776
|
+
if getv(from_object, ['thoughtSignature']) is not None:
|
2777
|
+
setv(
|
2778
|
+
to_object,
|
2779
|
+
['thought_signature'],
|
2780
|
+
getv(from_object, ['thoughtSignature']),
|
2781
|
+
)
|
2782
|
+
|
2762
2783
|
if getv(from_object, ['codeExecutionResult']) is not None:
|
2763
2784
|
setv(
|
2764
2785
|
to_object,
|
@@ -2821,6 +2842,13 @@ def _Part_from_vertex(
|
|
2821
2842
|
),
|
2822
2843
|
)
|
2823
2844
|
|
2845
|
+
if getv(from_object, ['thoughtSignature']) is not None:
|
2846
|
+
setv(
|
2847
|
+
to_object,
|
2848
|
+
['thought_signature'],
|
2849
|
+
getv(from_object, ['thoughtSignature']),
|
2850
|
+
)
|
2851
|
+
|
2824
2852
|
if getv(from_object, ['codeExecutionResult']) is not None:
|
2825
2853
|
setv(
|
2826
2854
|
to_object,
|
@@ -353,6 +353,13 @@ def _Part_to_mldev(
|
|
353
353
|
),
|
354
354
|
)
|
355
355
|
|
356
|
+
if getv(from_object, ['thought_signature']) is not None:
|
357
|
+
setv(
|
358
|
+
to_object,
|
359
|
+
['thoughtSignature'],
|
360
|
+
getv(from_object, ['thought_signature']),
|
361
|
+
)
|
362
|
+
|
356
363
|
if getv(from_object, ['code_execution_result']) is not None:
|
357
364
|
setv(
|
358
365
|
to_object,
|
@@ -415,6 +422,13 @@ def _Part_to_vertex(
|
|
415
422
|
),
|
416
423
|
)
|
417
424
|
|
425
|
+
if getv(from_object, ['thought_signature']) is not None:
|
426
|
+
setv(
|
427
|
+
to_object,
|
428
|
+
['thoughtSignature'],
|
429
|
+
getv(from_object, ['thought_signature']),
|
430
|
+
)
|
431
|
+
|
418
432
|
if getv(from_object, ['code_execution_result']) is not None:
|
419
433
|
setv(
|
420
434
|
to_object,
|
@@ -1585,7 +1599,7 @@ def _LiveConnectConfig_to_vertex(
|
|
1585
1599
|
return to_object
|
1586
1600
|
|
1587
1601
|
|
1588
|
-
def
|
1602
|
+
def _LiveConnectConstraints_to_mldev(
|
1589
1603
|
api_client: BaseApiClient,
|
1590
1604
|
from_object: Union[dict[str, Any], object],
|
1591
1605
|
parent_object: Optional[dict[str, Any]] = None,
|
@@ -1610,7 +1624,7 @@ def _LiveEphemeralParameters_to_mldev(
|
|
1610
1624
|
return to_object
|
1611
1625
|
|
1612
1626
|
|
1613
|
-
def
|
1627
|
+
def _LiveConnectConstraints_to_vertex(
|
1614
1628
|
api_client: BaseApiClient,
|
1615
1629
|
from_object: Union[dict[str, Any], object],
|
1616
1630
|
parent_object: Optional[dict[str, Any]] = None,
|
@@ -1645,13 +1659,13 @@ def _CreateAuthTokenConfig_to_mldev(
|
|
1645
1659
|
if getv(from_object, ['uses']) is not None:
|
1646
1660
|
setv(parent_object, ['uses'], getv(from_object, ['uses']))
|
1647
1661
|
|
1648
|
-
if getv(from_object, ['
|
1662
|
+
if getv(from_object, ['live_connect_constraints']) is not None:
|
1649
1663
|
setv(
|
1650
1664
|
parent_object,
|
1651
1665
|
['bidiGenerateContentSetup'],
|
1652
|
-
|
1666
|
+
_LiveConnectConstraints_to_mldev(
|
1653
1667
|
api_client,
|
1654
|
-
getv(from_object, ['
|
1668
|
+
getv(from_object, ['live_connect_constraints']),
|
1655
1669
|
to_object,
|
1656
1670
|
),
|
1657
1671
|
)
|
@@ -1684,9 +1698,9 @@ def _CreateAuthTokenConfig_to_vertex(
|
|
1684
1698
|
if getv(from_object, ['uses']) is not None:
|
1685
1699
|
raise ValueError('uses parameter is not supported in Vertex AI.')
|
1686
1700
|
|
1687
|
-
if getv(from_object, ['
|
1701
|
+
if getv(from_object, ['live_connect_constraints']) is not None:
|
1688
1702
|
raise ValueError(
|
1689
|
-
'
|
1703
|
+
'live_connect_constraints parameter is not supported in Vertex AI.'
|
1690
1704
|
)
|
1691
1705
|
|
1692
1706
|
if getv(from_object, ['lock_additional_fields']) is not None:
|
@@ -761,7 +761,8 @@ def process_schema(
|
|
761
761
|
schema_type = schema.get('type')
|
762
762
|
if isinstance(schema_type, Enum):
|
763
763
|
schema_type = schema_type.value
|
764
|
-
schema_type
|
764
|
+
if isinstance(schema_type, str):
|
765
|
+
schema_type = schema_type.upper()
|
765
766
|
|
766
767
|
# model_json_schema() returns a schema with a 'const' field when a Literal with one value is provided as a pydantic field
|
767
768
|
# For example `genre: Literal['action']` becomes: {'const': 'action', 'title': 'Genre', 'type': 'string'}
|
@@ -120,6 +120,13 @@ def _Part_to_mldev(
|
|
120
120
|
),
|
121
121
|
)
|
122
122
|
|
123
|
+
if getv(from_object, ['thought_signature']) is not None:
|
124
|
+
setv(
|
125
|
+
to_object,
|
126
|
+
['thoughtSignature'],
|
127
|
+
getv(from_object, ['thought_signature']),
|
128
|
+
)
|
129
|
+
|
123
130
|
if getv(from_object, ['code_execution_result']) is not None:
|
124
131
|
setv(
|
125
132
|
to_object,
|
@@ -785,6 +792,13 @@ def _Part_to_vertex(
|
|
785
792
|
),
|
786
793
|
)
|
787
794
|
|
795
|
+
if getv(from_object, ['thought_signature']) is not None:
|
796
|
+
setv(
|
797
|
+
to_object,
|
798
|
+
['thoughtSignature'],
|
799
|
+
getv(from_object, ['thought_signature']),
|
800
|
+
)
|
801
|
+
|
788
802
|
if getv(from_object, ['code_execution_result']) is not None:
|
789
803
|
setv(
|
790
804
|
to_object,
|
@@ -160,7 +160,7 @@ class _BaseChat:
|
|
160
160
|
# Because the AFC input contains the entire curated chat history in
|
161
161
|
# addition to the new user input, we need to truncate the AFC history
|
162
162
|
# to deduplicate the existing chat history.
|
163
|
-
automatic_function_calling_history[len(self._curated_history):]
|
163
|
+
automatic_function_calling_history[len(self._curated_history) :]
|
164
164
|
if automatic_function_calling_history
|
165
165
|
else [user_input]
|
166
166
|
)
|
@@ -328,7 +328,7 @@ class Chat(_BaseChat):
|
|
328
328
|
yield chunk
|
329
329
|
automatic_function_calling_history = (
|
330
330
|
chunk.automatic_function_calling_history
|
331
|
-
if chunk.automatic_function_calling_history
|
331
|
+
if chunk is not None and chunk.automatic_function_calling_history
|
332
332
|
else []
|
333
333
|
)
|
334
334
|
self.record_history(
|
@@ -495,9 +495,12 @@ class AsyncChat(_BaseChat):
|
|
495
495
|
self.record_history(
|
496
496
|
user_input=input_content,
|
497
497
|
model_output=output_contents,
|
498
|
-
automatic_function_calling_history=chunk.automatic_function_calling_history
|
498
|
+
automatic_function_calling_history=chunk.automatic_function_calling_history
|
499
|
+
if chunk is not None and chunk.automatic_function_calling_history
|
500
|
+
else [],
|
499
501
|
is_valid=is_valid,
|
500
502
|
)
|
503
|
+
|
501
504
|
return async_generator() # type: ignore[no-untyped-call, no-any-return]
|
502
505
|
|
503
506
|
|
@@ -34,6 +34,7 @@ from . import _live_converters as live_converters
|
|
34
34
|
from . import _mcp_utils
|
35
35
|
from . import _transformers as t
|
36
36
|
from . import client
|
37
|
+
from . import errors
|
37
38
|
from . import types
|
38
39
|
from ._api_client import BaseApiClient
|
39
40
|
from ._common import get_value_by_path as getv
|
@@ -78,10 +79,6 @@ _FUNCTION_RESPONSE_REQUIRES_ID = (
|
|
78
79
|
' response of a ToolCall.FunctionalCalls in Google AI.'
|
79
80
|
)
|
80
81
|
|
81
|
-
|
82
|
-
_DUMMY_KEY = 'dummy_key'
|
83
|
-
|
84
|
-
|
85
82
|
class AsyncSession:
|
86
83
|
"""[Preview] AsyncSession."""
|
87
84
|
|
@@ -912,25 +909,10 @@ class AsyncLive(_api_module.BaseModule):
|
|
912
909
|
Yields:
|
913
910
|
An AsyncSession object.
|
914
911
|
"""
|
915
|
-
async with self._connect(
|
916
|
-
model=model,
|
917
|
-
config=config,
|
918
|
-
) as session:
|
919
|
-
yield session
|
920
|
-
|
921
|
-
@contextlib.asynccontextmanager
|
922
|
-
async def _connect(
|
923
|
-
self,
|
924
|
-
*,
|
925
|
-
model: Optional[str] = None,
|
926
|
-
config: Optional[types.LiveConnectConfigOrDict] = None,
|
927
|
-
uri: Optional[str] = None,
|
928
|
-
) -> AsyncIterator[AsyncSession]:
|
929
|
-
|
930
912
|
# TODO(b/404946570): Support per request http options.
|
931
913
|
if isinstance(config, dict):
|
932
914
|
config = types.LiveConnectConfig(**config)
|
933
|
-
if config and config.http_options
|
915
|
+
if config and config.http_options:
|
934
916
|
raise ValueError(
|
935
917
|
'google.genai.client.aio.live.connect() does not support'
|
936
918
|
' http_options at request-level in LiveConnectConfig yet. Please use'
|
@@ -945,10 +927,22 @@ class AsyncLive(_api_module.BaseModule):
|
|
945
927
|
parameter_model = await _t_live_connect_config(self._api_client, config)
|
946
928
|
|
947
929
|
if self._api_client.api_key and not self._api_client.vertexai:
|
948
|
-
api_key = self._api_client.api_key
|
949
930
|
version = self._api_client._http_options.api_version
|
950
|
-
|
951
|
-
|
931
|
+
api_key = self._api_client.api_key
|
932
|
+
method = 'BidiGenerateContent'
|
933
|
+
key_name = 'key'
|
934
|
+
if api_key.startswith('auth_tokens/'):
|
935
|
+
warnings.warn(
|
936
|
+
message=(
|
937
|
+
"The SDK's ephemeral token support is experimental, and may"
|
938
|
+
' change in future versions.'
|
939
|
+
),
|
940
|
+
category=errors.ExperimentalWarning,
|
941
|
+
)
|
942
|
+
method = 'BidiGenerateContentConstrained'
|
943
|
+
key_name = 'access_token'
|
944
|
+
|
945
|
+
uri = f'{base_url}/ws/google.ai.generativelanguage.{version}.GenerativeService.{method}?{key_name}={api_key}'
|
952
946
|
headers = self._api_client._http_options.headers
|
953
947
|
|
954
948
|
request_dict = _common.convert_to_dict(
|
@@ -969,8 +963,7 @@ class AsyncLive(_api_module.BaseModule):
|
|
969
963
|
# Headers already contains api key for express mode.
|
970
964
|
api_key = self._api_client.api_key
|
971
965
|
version = self._api_client._http_options.api_version
|
972
|
-
|
973
|
-
uri = f'{base_url}/ws/google.cloud.aiplatform.{version}.LlmBidiService/BidiGenerateContent'
|
966
|
+
uri = f'{base_url}/ws/google.cloud.aiplatform.{version}.LlmBidiService/BidiGenerateContent'
|
974
967
|
headers = self._api_client._http_options.headers
|
975
968
|
|
976
969
|
request_dict = _common.convert_to_dict(
|
@@ -1060,83 +1053,6 @@ class AsyncLive(_api_module.BaseModule):
|
|
1060
1053
|
yield AsyncSession(api_client=self._api_client, websocket=ws)
|
1061
1054
|
|
1062
1055
|
|
1063
|
-
@_common.experimental_warning(
|
1064
|
-
"The SDK's Live API connection with ephemeral token implementation is"
|
1065
|
-
' experimental, and may change in future versions.',
|
1066
|
-
)
|
1067
|
-
@contextlib.asynccontextmanager
|
1068
|
-
async def live_ephemeral_connect(
|
1069
|
-
access_token: str,
|
1070
|
-
model: Optional[str] = None,
|
1071
|
-
config: Optional[types.LiveConnectConfigOrDict] = None,
|
1072
|
-
) -> AsyncIterator[AsyncSession]:
|
1073
|
-
"""[Experimental] Connect to the live server using ephermeral token (Gemini Developer API only).
|
1074
|
-
|
1075
|
-
Note: the live API is currently in experimental.
|
1076
|
-
|
1077
|
-
Usage:
|
1078
|
-
|
1079
|
-
.. code-block:: python
|
1080
|
-
from google import genai
|
1081
|
-
|
1082
|
-
config = {}
|
1083
|
-
async with genai.live_ephemeral_connect(
|
1084
|
-
access_token='auth_tokens/12345',
|
1085
|
-
model='...',
|
1086
|
-
config=config,
|
1087
|
-
http_options=types.HttpOptions(api_version='v1beta'),
|
1088
|
-
) as session:
|
1089
|
-
await session.send_client_content(
|
1090
|
-
turns=types.Content(
|
1091
|
-
role='user',
|
1092
|
-
parts=[types.Part(text='hello!')]
|
1093
|
-
),
|
1094
|
-
turn_complete=True
|
1095
|
-
)
|
1096
|
-
|
1097
|
-
async for message in session.receive():
|
1098
|
-
print(message)
|
1099
|
-
|
1100
|
-
Args:
|
1101
|
-
access_token: The access token to use for the Live session. It can be
|
1102
|
-
generated by the `client.tokens.create` method.
|
1103
|
-
model: The model to use for the Live session.
|
1104
|
-
config: The configuration for the Live session.
|
1105
|
-
|
1106
|
-
Yields:
|
1107
|
-
An AsyncSession object.
|
1108
|
-
"""
|
1109
|
-
if isinstance(config, dict):
|
1110
|
-
config = types.LiveConnectConfig(**config)
|
1111
|
-
|
1112
|
-
http_options = config.http_options if config else None
|
1113
|
-
|
1114
|
-
base_url = (
|
1115
|
-
http_options.base_url
|
1116
|
-
if http_options and http_options.base_url
|
1117
|
-
else 'https://generativelanguage.googleapis.com/'
|
1118
|
-
)
|
1119
|
-
api_version = (
|
1120
|
-
http_options.api_version
|
1121
|
-
if http_options and http_options.api_version
|
1122
|
-
else 'v1beta'
|
1123
|
-
)
|
1124
|
-
internal_client = client.Client(
|
1125
|
-
api_key=_DUMMY_KEY, # Can't be None during initialization
|
1126
|
-
http_options=types.HttpOptions(
|
1127
|
-
base_url=base_url,
|
1128
|
-
api_version=api_version,
|
1129
|
-
),
|
1130
|
-
)
|
1131
|
-
websocket_base_url = internal_client._api_client._websocket_base_url()
|
1132
|
-
uri = f'{websocket_base_url}/ws/google.ai.generativelanguage.{api_version}.GenerativeService.BidiGenerateContentConstrained?access_token={access_token}'
|
1133
|
-
|
1134
|
-
async with internal_client.aio.live._connect(
|
1135
|
-
model=model, config=config, uri=uri
|
1136
|
-
) as session:
|
1137
|
-
yield session
|
1138
|
-
|
1139
|
-
|
1140
1056
|
async def _t_live_connect_config(
|
1141
1057
|
api_client: BaseApiClient,
|
1142
1058
|
config: Optional[types.LiveConnectConfigOrDict],
|
@@ -123,6 +123,13 @@ def _Part_to_mldev(
|
|
123
123
|
),
|
124
124
|
)
|
125
125
|
|
126
|
+
if getv(from_object, ['thought_signature']) is not None:
|
127
|
+
setv(
|
128
|
+
to_object,
|
129
|
+
['thoughtSignature'],
|
130
|
+
getv(from_object, ['thought_signature']),
|
131
|
+
)
|
132
|
+
|
126
133
|
if getv(from_object, ['code_execution_result']) is not None:
|
127
134
|
setv(
|
128
135
|
to_object,
|
@@ -1548,6 +1555,13 @@ def _Part_to_vertex(
|
|
1548
1555
|
),
|
1549
1556
|
)
|
1550
1557
|
|
1558
|
+
if getv(from_object, ['thought_signature']) is not None:
|
1559
|
+
setv(
|
1560
|
+
to_object,
|
1561
|
+
['thoughtSignature'],
|
1562
|
+
getv(from_object, ['thought_signature']),
|
1563
|
+
)
|
1564
|
+
|
1551
1565
|
if getv(from_object, ['code_execution_result']) is not None:
|
1552
1566
|
setv(
|
1553
1567
|
to_object,
|
@@ -3441,6 +3455,13 @@ def _Part_from_mldev(
|
|
3441
3455
|
),
|
3442
3456
|
)
|
3443
3457
|
|
3458
|
+
if getv(from_object, ['thoughtSignature']) is not None:
|
3459
|
+
setv(
|
3460
|
+
to_object,
|
3461
|
+
['thought_signature'],
|
3462
|
+
getv(from_object, ['thoughtSignature']),
|
3463
|
+
)
|
3464
|
+
|
3444
3465
|
if getv(from_object, ['codeExecutionResult']) is not None:
|
3445
3466
|
setv(
|
3446
3467
|
to_object,
|
@@ -4138,6 +4159,13 @@ def _Part_from_vertex(
|
|
4138
4159
|
),
|
4139
4160
|
)
|
4140
4161
|
|
4162
|
+
if getv(from_object, ['thoughtSignature']) is not None:
|
4163
|
+
setv(
|
4164
|
+
to_object,
|
4165
|
+
['thought_signature'],
|
4166
|
+
getv(from_object, ['thoughtSignature']),
|
4167
|
+
)
|
4168
|
+
|
4141
4169
|
if getv(from_object, ['codeExecutionResult']) is not None:
|
4142
4170
|
setv(
|
4143
4171
|
to_object,
|
@@ -6105,7 +6133,8 @@ class Models(_api_module.BaseModule):
|
|
6105
6133
|
)
|
6106
6134
|
yield chunk
|
6107
6135
|
if (
|
6108
|
-
|
6136
|
+
chunk is None
|
6137
|
+
or not chunk.candidates
|
6109
6138
|
or not chunk.candidates[0].content
|
6110
6139
|
or not chunk.candidates[0].content.parts
|
6111
6140
|
):
|
@@ -6120,7 +6149,7 @@ class Models(_api_module.BaseModule):
|
|
6120
6149
|
break
|
6121
6150
|
|
6122
6151
|
# Append function response parts to contents for the next request.
|
6123
|
-
if chunk.candidates is not None:
|
6152
|
+
if chunk is not None and chunk.candidates is not None:
|
6124
6153
|
func_call_content = chunk.candidates[0].content
|
6125
6154
|
func_response_content = types.Content(
|
6126
6155
|
role='user',
|
@@ -7609,7 +7638,8 @@ class AsyncModels(_api_module.BaseModule):
|
|
7609
7638
|
)
|
7610
7639
|
yield chunk
|
7611
7640
|
if (
|
7612
|
-
|
7641
|
+
chunk is None
|
7642
|
+
or not chunk.candidates
|
7613
7643
|
or not chunk.candidates[0].content
|
7614
7644
|
or not chunk.candidates[0].content.parts
|
7615
7645
|
):
|
@@ -7623,6 +7653,8 @@ class AsyncModels(_api_module.BaseModule):
|
|
7623
7653
|
if not func_response_parts:
|
7624
7654
|
break
|
7625
7655
|
|
7656
|
+
if chunk is None:
|
7657
|
+
continue
|
7626
7658
|
# Append function response parts to contents for the next request.
|
7627
7659
|
func_call_content = chunk.candidates[0].content
|
7628
7660
|
func_response_content = types.Content(
|
@@ -225,6 +225,8 @@ class FinishReason(_common.CaseInSensitiveEnum):
|
|
225
225
|
"""The function call generated by the model is invalid."""
|
226
226
|
IMAGE_SAFETY = 'IMAGE_SAFETY'
|
227
227
|
"""Token generation stopped because generated images have safety violations."""
|
228
|
+
UNEXPECTED_TOOL_CALL = 'UNEXPECTED_TOOL_CALL'
|
229
|
+
"""The tool call generated by the model is invalid."""
|
228
230
|
|
229
231
|
|
230
232
|
class HarmProbability(_common.CaseInSensitiveEnum):
|
@@ -887,6 +889,10 @@ class Part(_common.BaseModel):
|
|
887
889
|
file_data: Optional[FileData] = Field(
|
888
890
|
default=None, description="""Optional. URI based data."""
|
889
891
|
)
|
892
|
+
thought_signature: Optional[bytes] = Field(
|
893
|
+
default=None,
|
894
|
+
description="""An opaque signature for the thought so it can be reused in subsequent requests.""",
|
895
|
+
)
|
890
896
|
code_execution_result: Optional[CodeExecutionResult] = Field(
|
891
897
|
default=None,
|
892
898
|
description="""Optional. Result of executing the [ExecutableCode].""",
|
@@ -984,6 +990,9 @@ class PartDict(TypedDict, total=False):
|
|
984
990
|
file_data: Optional[FileDataDict]
|
985
991
|
"""Optional. URI based data."""
|
986
992
|
|
993
|
+
thought_signature: Optional[bytes]
|
994
|
+
"""An opaque signature for the thought so it can be reused in subsequent requests."""
|
995
|
+
|
987
996
|
code_execution_result: Optional[CodeExecutionResultDict]
|
988
997
|
"""Optional. Result of executing the [ExecutableCode]."""
|
989
998
|
|
@@ -12492,8 +12501,8 @@ class AuthTokenDict(TypedDict, total=False):
|
|
12492
12501
|
AuthTokenOrDict = Union[AuthToken, AuthTokenDict]
|
12493
12502
|
|
12494
12503
|
|
12495
|
-
class
|
12496
|
-
"""Config for
|
12504
|
+
class LiveConnectConstraints(_common.BaseModel):
|
12505
|
+
"""Config for LiveConnectConstraints for Auth Token creation."""
|
12497
12506
|
|
12498
12507
|
model: Optional[str] = Field(
|
12499
12508
|
default=None,
|
@@ -12507,8 +12516,8 @@ class LiveEphemeralParameters(_common.BaseModel):
|
|
12507
12516
|
)
|
12508
12517
|
|
12509
12518
|
|
12510
|
-
class
|
12511
|
-
"""Config for
|
12519
|
+
class LiveConnectConstraintsDict(TypedDict, total=False):
|
12520
|
+
"""Config for LiveConnectConstraints for Auth Token creation."""
|
12512
12521
|
|
12513
12522
|
model: Optional[str]
|
12514
12523
|
"""ID of the model to configure in the ephemeral token for Live API.
|
@@ -12519,8 +12528,8 @@ class LiveEphemeralParametersDict(TypedDict, total=False):
|
|
12519
12528
|
"""Configuration specific to Live API connections created using this token."""
|
12520
12529
|
|
12521
12530
|
|
12522
|
-
|
12523
|
-
|
12531
|
+
LiveConnectConstraintsOrDict = Union[
|
12532
|
+
LiveConnectConstraints, LiveConnectConstraintsDict
|
12524
12533
|
]
|
12525
12534
|
|
12526
12535
|
|
@@ -12553,7 +12562,7 @@ class CreateAuthTokenConfig(_common.BaseModel):
|
|
12553
12562
|
then no limit is applied. Default is 1. Resuming a Live API session does
|
12554
12563
|
not count as a use.""",
|
12555
12564
|
)
|
12556
|
-
|
12565
|
+
live_connect_constraints: Optional[LiveConnectConstraints] = Field(
|
12557
12566
|
default=None,
|
12558
12567
|
description="""Configuration specific to Live API connections created using this token.""",
|
12559
12568
|
)
|
@@ -12589,7 +12598,7 @@ class CreateAuthTokenConfigDict(TypedDict, total=False):
|
|
12589
12598
|
then no limit is applied. Default is 1. Resuming a Live API session does
|
12590
12599
|
not count as a use."""
|
12591
12600
|
|
12592
|
-
|
12601
|
+
live_connect_constraints: Optional[LiveConnectConstraintsDict]
|
12593
12602
|
"""Configuration specific to Live API connections created using this token."""
|
12594
12603
|
|
12595
12604
|
lock_additional_fields: Optional[list[str]]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{google_genai-1.17.0 → google_genai-1.18.0}/google/genai/_automatic_function_calling_util.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|