google-genai 1.15.0__tar.gz → 1.16.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.15.0/google_genai.egg-info → google_genai-1.16.0}/PKG-INFO +8 -4
- {google_genai-1.15.0 → google_genai-1.16.0}/README.md +7 -3
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/__init__.py +5 -3
- google_genai-1.16.0/google/genai/_adapters.py +55 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_api_client.py +3 -3
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_api_module.py +1 -1
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_automatic_function_calling_util.py +1 -1
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_common.py +1 -1
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_extra_utils.py +117 -9
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_live_converters.py +1295 -20
- google_genai-1.16.0/google/genai/_mcp_utils.py +117 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_replay_api_client.py +1 -1
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_test_api_client.py +1 -1
- google_genai-1.16.0/google/genai/_tokens_converters.py +1701 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_transformers.py +66 -33
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/caches.py +223 -20
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/chats.py +1 -1
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/client.py +12 -1
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/errors.py +1 -1
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/live.py +218 -35
- google_genai-1.16.0/google/genai/live_music.py +201 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/models.py +505 -44
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/pagers.py +1 -1
- google_genai-1.16.0/google/genai/tokens.py +357 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/types.py +7887 -6765
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/version.py +2 -2
- {google_genai-1.15.0 → google_genai-1.16.0/google_genai.egg-info}/PKG-INFO +8 -4
- {google_genai-1.15.0 → google_genai-1.16.0}/google_genai.egg-info/SOURCES.txt +5 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/pyproject.toml +1 -1
- {google_genai-1.15.0 → google_genai-1.16.0}/LICENSE +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/MANIFEST.in +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/_base_url.py +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/batches.py +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/files.py +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/operations.py +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/py.typed +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google/genai/tunings.py +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google_genai.egg-info/dependency_links.txt +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google_genai.egg-info/requires.txt +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/google_genai.egg-info/top_level.txt +0 -0
- {google_genai-1.15.0 → google_genai-1.16.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: google-genai
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.16.0
|
4
4
|
Summary: GenAI Python SDK
|
5
5
|
Author-email: Google LLC <googleapis-packages@google.com>
|
6
6
|
License: Apache-2.0
|
@@ -40,7 +40,11 @@ Dynamic: license-file
|
|
40
40
|
|
41
41
|
-----
|
42
42
|
|
43
|
-
Google Gen AI Python SDK provides an interface for developers to integrate
|
43
|
+
Google Gen AI Python SDK provides an interface for developers to integrate
|
44
|
+
Google's generative models into their Python applications. It supports the
|
45
|
+
[Gemini Developer API](https://ai.google.dev/gemini-api/docs) and
|
46
|
+
[Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview)
|
47
|
+
APIs.
|
44
48
|
|
45
49
|
## Installation
|
46
50
|
|
@@ -88,8 +92,8 @@ Developer API or the Gemini API in Vertex AI.
|
|
88
92
|
export GOOGLE_API_KEY='your-api-key'
|
89
93
|
```
|
90
94
|
|
91
|
-
**Gemini API on Vertex AI:** Set `GOOGLE_GENAI_USE_VERTEXAI`,
|
92
|
-
and `GOOGLE_CLOUD_LOCATION`, as shown below:
|
95
|
+
**Gemini API on Vertex AI:** Set `GOOGLE_GENAI_USE_VERTEXAI`,
|
96
|
+
`GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`, as shown below:
|
93
97
|
|
94
98
|
```bash
|
95
99
|
export GOOGLE_GENAI_USE_VERTEXAI=true
|
@@ -9,7 +9,11 @@
|
|
9
9
|
|
10
10
|
-----
|
11
11
|
|
12
|
-
Google Gen AI Python SDK provides an interface for developers to integrate
|
12
|
+
Google Gen AI Python SDK provides an interface for developers to integrate
|
13
|
+
Google's generative models into their Python applications. It supports the
|
14
|
+
[Gemini Developer API](https://ai.google.dev/gemini-api/docs) and
|
15
|
+
[Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview)
|
16
|
+
APIs.
|
13
17
|
|
14
18
|
## Installation
|
15
19
|
|
@@ -57,8 +61,8 @@ Developer API or the Gemini API in Vertex AI.
|
|
57
61
|
export GOOGLE_API_KEY='your-api-key'
|
58
62
|
```
|
59
63
|
|
60
|
-
**Gemini API on Vertex AI:** Set `GOOGLE_GENAI_USE_VERTEXAI`,
|
61
|
-
and `GOOGLE_CLOUD_LOCATION`, as shown below:
|
64
|
+
**Gemini API on Vertex AI:** Set `GOOGLE_GENAI_USE_VERTEXAI`,
|
65
|
+
`GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`, as shown below:
|
62
66
|
|
63
67
|
```bash
|
64
68
|
export GOOGLE_GENAI_USE_VERTEXAI=true
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2025 Google LLC
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -15,9 +15,11 @@
|
|
15
15
|
|
16
16
|
"""Google Gen AI SDK"""
|
17
17
|
|
18
|
+
from . import version
|
18
19
|
from .client import Client
|
19
|
-
from . import
|
20
|
+
from .live import live_ephemeral_connect
|
21
|
+
|
20
22
|
|
21
23
|
__version__ = version.__version__
|
22
24
|
|
23
|
-
__all__ = ['Client']
|
25
|
+
__all__ = ['Client', 'live_ephemeral_connect']
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
#
|
15
|
+
|
16
|
+
import typing
|
17
|
+
|
18
|
+
from ._mcp_utils import mcp_to_gemini_tools
|
19
|
+
from .types import FunctionCall, Tool
|
20
|
+
|
21
|
+
if typing.TYPE_CHECKING:
|
22
|
+
from mcp import types as mcp_types
|
23
|
+
from mcp import ClientSession
|
24
|
+
|
25
|
+
|
26
|
+
class McpToGenAiToolAdapter:
|
27
|
+
"""Adapter for working with MCP tools in a GenAI client."""
|
28
|
+
|
29
|
+
def __init__(
|
30
|
+
self,
|
31
|
+
session: "mcp.ClientSession", # type: ignore # noqa: F821
|
32
|
+
list_tools_result: "mcp_types.ListToolsResult", # type: ignore
|
33
|
+
) -> None:
|
34
|
+
self._mcp_session = session
|
35
|
+
self._list_tools_result = list_tools_result
|
36
|
+
|
37
|
+
async def call_tool(
|
38
|
+
self, function_call: FunctionCall
|
39
|
+
) -> "mcp_types.CallToolResult": # type: ignore
|
40
|
+
"""Calls a function on the MCP server."""
|
41
|
+
name = function_call.name if function_call.name else ""
|
42
|
+
arguments = dict(function_call.args) if function_call.args else {}
|
43
|
+
|
44
|
+
return typing.cast(
|
45
|
+
"mcp_types.CallToolResult",
|
46
|
+
await self._mcp_session.call_tool(
|
47
|
+
name=name,
|
48
|
+
arguments=arguments,
|
49
|
+
),
|
50
|
+
)
|
51
|
+
|
52
|
+
@property
|
53
|
+
def tools(self) -> list[Tool]:
|
54
|
+
"""Returns a list of Google GenAI tools."""
|
55
|
+
return mcp_to_gemini_tools(self._list_tools_result.tools)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2025 Google LLC
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -72,14 +72,14 @@ def _append_library_version_headers(headers: dict[str, str]) -> None:
|
|
72
72
|
'user-agent' in headers
|
73
73
|
and version_header_value not in headers['user-agent']
|
74
74
|
):
|
75
|
-
headers['user-agent']
|
75
|
+
headers['user-agent'] = f'{version_header_value} ' + headers['user-agent']
|
76
76
|
elif 'user-agent' not in headers:
|
77
77
|
headers['user-agent'] = version_header_value
|
78
78
|
if (
|
79
79
|
'x-goog-api-client' in headers
|
80
80
|
and version_header_value not in headers['x-goog-api-client']
|
81
81
|
):
|
82
|
-
headers['x-goog-api-client']
|
82
|
+
headers['x-goog-api-client'] = f'{version_header_value} ' + headers['x-goog-api-client']
|
83
83
|
elif 'x-goog-api-client' not in headers:
|
84
84
|
headers['x-goog-api-client'] = version_header_value
|
85
85
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2025 Google LLC
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -24,14 +24,30 @@ from typing import Any, Callable, Dict, Optional, Union, get_args, get_origin
|
|
24
24
|
import pydantic
|
25
25
|
|
26
26
|
from . import _common
|
27
|
+
from . import _mcp_utils
|
27
28
|
from . import errors
|
28
29
|
from . import types
|
30
|
+
from ._adapters import McpToGenAiToolAdapter
|
31
|
+
|
29
32
|
|
30
33
|
if sys.version_info >= (3, 10):
|
31
34
|
from types import UnionType
|
32
35
|
else:
|
33
36
|
UnionType = typing._UnionGenericAlias # type: ignore[attr-defined]
|
34
37
|
|
38
|
+
if typing.TYPE_CHECKING:
|
39
|
+
from mcp import ClientSession as McpClientSession
|
40
|
+
from mcp.types import Tool as McpTool
|
41
|
+
else:
|
42
|
+
McpClientSession: typing.Type = Any
|
43
|
+
McpTool: typing.Type = Any
|
44
|
+
try:
|
45
|
+
from mcp import ClientSession as McpClientSession
|
46
|
+
from mcp.types import Tool as McpTool
|
47
|
+
except ImportError:
|
48
|
+
McpClientSession = None
|
49
|
+
McpTool = None
|
50
|
+
|
35
51
|
_DEFAULT_MAX_REMOTE_CALLS_AFC = 10
|
36
52
|
|
37
53
|
logger = logging.getLogger('google_genai.models')
|
@@ -78,10 +94,13 @@ def format_destination(
|
|
78
94
|
|
79
95
|
def get_function_map(
|
80
96
|
config: Optional[types.GenerateContentConfigOrDict] = None,
|
97
|
+
mcp_to_genai_tool_adapters: Optional[
|
98
|
+
dict[str, McpToGenAiToolAdapter]
|
99
|
+
] = None,
|
81
100
|
is_caller_method_async: bool = False,
|
82
|
-
) -> dict[str, Callable[..., Any]]:
|
101
|
+
) -> dict[str, Union[Callable[..., Any], McpToGenAiToolAdapter]]:
|
83
102
|
"""Returns a function map from the config."""
|
84
|
-
function_map: dict[str, Callable[..., Any]] = {}
|
103
|
+
function_map: dict[str, Union[Callable[..., Any], McpToGenAiToolAdapter]] = {}
|
85
104
|
if not config:
|
86
105
|
return function_map
|
87
106
|
config_model = _create_generate_content_config_model(config)
|
@@ -95,6 +114,17 @@ def get_function_map(
|
|
95
114
|
f' invoke {tool.__name__} to get the function response.'
|
96
115
|
)
|
97
116
|
function_map[tool.__name__] = tool
|
117
|
+
if mcp_to_genai_tool_adapters:
|
118
|
+
if not is_caller_method_async:
|
119
|
+
raise errors.UnsupportedFunctionError(
|
120
|
+
'MCP tools are not supported in synchronous methods.'
|
121
|
+
)
|
122
|
+
for tool_name, _ in mcp_to_genai_tool_adapters.items():
|
123
|
+
if function_map.get(tool_name):
|
124
|
+
raise ValueError(
|
125
|
+
f'Tool {tool_name} is already defined for the request.'
|
126
|
+
)
|
127
|
+
function_map.update(mcp_to_genai_tool_adapters)
|
98
128
|
return function_map
|
99
129
|
|
100
130
|
|
@@ -247,7 +277,7 @@ async def invoke_function_from_dict_args_async(
|
|
247
277
|
|
248
278
|
def get_function_response_parts(
|
249
279
|
response: types.GenerateContentResponse,
|
250
|
-
function_map: dict[str, Callable[..., Any]],
|
280
|
+
function_map: dict[str, Union[Callable[..., Any], McpToGenAiToolAdapter]],
|
251
281
|
) -> list[types.Part]:
|
252
282
|
"""Returns the function response parts from the response."""
|
253
283
|
func_response_parts = []
|
@@ -267,9 +297,10 @@ def get_function_response_parts(
|
|
267
297
|
)
|
268
298
|
func_response: dict[str, Any]
|
269
299
|
try:
|
270
|
-
|
271
|
-
|
272
|
-
|
300
|
+
if not isinstance(func, McpToGenAiToolAdapter):
|
301
|
+
func_response = {
|
302
|
+
'result': invoke_function_from_dict_args(args, func)
|
303
|
+
}
|
273
304
|
except Exception as e: # pylint: disable=broad-except
|
274
305
|
func_response = {'error': str(e)}
|
275
306
|
func_response_part = types.Part.from_function_response(
|
@@ -278,9 +309,10 @@ def get_function_response_parts(
|
|
278
309
|
func_response_parts.append(func_response_part)
|
279
310
|
return func_response_parts
|
280
311
|
|
312
|
+
|
281
313
|
async def get_function_response_parts_async(
|
282
314
|
response: types.GenerateContentResponse,
|
283
|
-
function_map: dict[str, Callable[..., Any]],
|
315
|
+
function_map: dict[str, Union[Callable[..., Any], McpToGenAiToolAdapter]],
|
284
316
|
) -> list[types.Part]:
|
285
317
|
"""Returns the function response parts from the response."""
|
286
318
|
func_response_parts = []
|
@@ -300,7 +332,15 @@ async def get_function_response_parts_async(
|
|
300
332
|
)
|
301
333
|
func_response: dict[str, Any]
|
302
334
|
try:
|
303
|
-
if
|
335
|
+
if isinstance(func, McpToGenAiToolAdapter):
|
336
|
+
mcp_tool_response = await func.call_tool(
|
337
|
+
types.FunctionCall(name=func_name, args=args)
|
338
|
+
)
|
339
|
+
if mcp_tool_response.isError:
|
340
|
+
func_response = {'error': mcp_tool_response}
|
341
|
+
else:
|
342
|
+
func_response = {'result': mcp_tool_response}
|
343
|
+
elif inspect.iscoroutinefunction(func):
|
304
344
|
func_response = {
|
305
345
|
'result': await invoke_function_from_dict_args_async(args, func)
|
306
346
|
}
|
@@ -401,3 +441,71 @@ def should_append_afc_history(
|
|
401
441
|
if not config_model.automatic_function_calling:
|
402
442
|
return True
|
403
443
|
return not config_model.automatic_function_calling.ignore_call_history
|
444
|
+
|
445
|
+
|
446
|
+
def parse_config_for_mcp_usage(
|
447
|
+
config: Optional[types.GenerateContentConfigOrDict] = None,
|
448
|
+
) -> Optional[types.GenerateContentConfig]:
|
449
|
+
"""Returns a parsed config with an appended MCP header if MCP tools or sessions are used."""
|
450
|
+
if not config:
|
451
|
+
return None
|
452
|
+
config_model = _create_generate_content_config_model(config)
|
453
|
+
# Create a copy of the config model with the tools field cleared since some
|
454
|
+
# tools may not be pickleable.
|
455
|
+
config_model_copy = config_model.model_copy(update={'tools': None})
|
456
|
+
config_model_copy.tools = config_model.tools
|
457
|
+
if config_model.tools and _mcp_utils.has_mcp_tool_usage(config_model.tools):
|
458
|
+
if config_model_copy.http_options is None:
|
459
|
+
config_model_copy.http_options = types.HttpOptions(headers={})
|
460
|
+
if config_model_copy.http_options.headers is None:
|
461
|
+
config_model_copy.http_options.headers = {}
|
462
|
+
_mcp_utils.set_mcp_usage_header(config_model_copy.http_options.headers)
|
463
|
+
|
464
|
+
return config_model_copy
|
465
|
+
|
466
|
+
|
467
|
+
async def parse_config_for_mcp_sessions(
|
468
|
+
config: Optional[types.GenerateContentConfigOrDict] = None,
|
469
|
+
) -> tuple[
|
470
|
+
Optional[types.GenerateContentConfig],
|
471
|
+
dict[str, McpToGenAiToolAdapter],
|
472
|
+
]:
|
473
|
+
"""Returns a parsed config with MCP sessions converted to GenAI tools.
|
474
|
+
|
475
|
+
Also returns a map of MCP tools to GenAI tool adapters to be used for AFC.
|
476
|
+
"""
|
477
|
+
mcp_to_genai_tool_adapters: dict[str, McpToGenAiToolAdapter] = {}
|
478
|
+
parsed_config = parse_config_for_mcp_usage(config)
|
479
|
+
if not parsed_config:
|
480
|
+
return None, mcp_to_genai_tool_adapters
|
481
|
+
# Create a copy of the config model with the tools field cleared as they will
|
482
|
+
# be replaced with the MCP tools converted to GenAI tools.
|
483
|
+
parsed_config_copy = parsed_config.model_copy(update={'tools': None})
|
484
|
+
if parsed_config.tools:
|
485
|
+
parsed_config_copy.tools = []
|
486
|
+
for tool in parsed_config.tools:
|
487
|
+
if McpClientSession is not None and isinstance(tool, McpClientSession):
|
488
|
+
mcp_to_genai_tool_adapter = McpToGenAiToolAdapter(
|
489
|
+
tool, await tool.list_tools()
|
490
|
+
)
|
491
|
+
# Extend the config with the MCP session tools converted to GenAI tools.
|
492
|
+
parsed_config_copy.tools.extend(mcp_to_genai_tool_adapter.tools)
|
493
|
+
for genai_tool in mcp_to_genai_tool_adapter.tools:
|
494
|
+
if genai_tool.function_declarations:
|
495
|
+
for function_declaration in genai_tool.function_declarations:
|
496
|
+
if function_declaration.name:
|
497
|
+
if mcp_to_genai_tool_adapters.get(function_declaration.name):
|
498
|
+
raise ValueError(
|
499
|
+
f'Tool {function_declaration.name} is already defined for'
|
500
|
+
' the request.'
|
501
|
+
)
|
502
|
+
mcp_to_genai_tool_adapters[function_declaration.name] = (
|
503
|
+
mcp_to_genai_tool_adapter
|
504
|
+
)
|
505
|
+
if McpClientSession is not None:
|
506
|
+
parsed_config_copy.tools.extend(
|
507
|
+
tool
|
508
|
+
for tool in parsed_config.tools
|
509
|
+
if not isinstance(tool, McpClientSession)
|
510
|
+
)
|
511
|
+
return parsed_config_copy, mcp_to_genai_tool_adapters
|