Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

from .log import logger
from .models import ChatModels
from .tools import GeminiTool
from .utils import create_tools_config, to_response_format
from .version import __version__

Expand Down Expand Up @@ -451,7 +452,9 @@ async def _run(self) -> None:

turns = [types.Content.model_validate(turn) for turn in turns_dict]
tool_context = llm.ToolContext(self._tools)
tools_config = create_tools_config(tool_context, _only_single_type=True)
tools_config = create_tools_config(
tool_context, allow_mixed_tools=_is_gemini_3_model(self._model)
)
# Gemini's API rejects `generateContent` requests that pass
# `cached_content` together with `system_instruction`, `tools`,
# or `tool_config` — those fields must live INSIDE the
Expand All @@ -460,6 +463,32 @@ async def _run(self) -> None:
# here we just suppress the duplicates on the outgoing request
# whenever a cache is attached.
using_cache = "cached_content" in self._extra_kwargs
# combining built-in + function tools requires include_server_side_tool_invocations
# (skip when caching: tool_config must be baked into the cache, dropped below)
has_function_tools = bool(tool_context.function_tools)
has_provider_tools = any(
isinstance(tool, GeminiTool) for tool in tool_context.provider_tools
)
if (
not using_cache
and has_function_tools
and has_provider_tools
and _is_gemini_3_model(self._model)
):
tool_config = self._extra_kwargs.get("tool_config")
if not isinstance(tool_config, types.ToolConfig):
tool_config = types.ToolConfig()
self._extra_kwargs["tool_config"] = tool_config
tool_config.include_server_side_tool_invocations = True
# AUTO is unsupported alongside built-in tools; VALIDATED keeps the same
# behavior. https://ai.google.dev/gemini-api/docs/tool-combination
fcc = tool_config.function_calling_config
if fcc is not None and fcc.mode == types.FunctionCallingConfigMode.AUTO:
logger.debug(
"upgrading function_calling_config AUTO->VALIDATED: AUTO is "
"unsupported when combining built-in and function tools"
)
fcc.mode = types.FunctionCallingConfigMode.VALIDATED
if tools_config and not using_cache:
self._extra_kwargs["tools"] = tools_config
elif using_cache:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from livekit.agents.types import NOT_GIVEN, NotGivenOr
from livekit.agents.utils import is_given

from .log import logger
from .tools import GeminiTool

__all__ = ["create_tools_config"]
Expand All @@ -22,7 +23,7 @@ def create_tools_config(
*,
tool_behavior: NotGivenOr[types.Behavior] = NOT_GIVEN,
use_parameters_json_schema: bool = True,
_only_single_type: bool = False,
allow_mixed_tools: bool = True,
) -> list[types.Tool]:
gemini_tools: list[types.Tool] = []

Expand All @@ -37,14 +38,18 @@ def create_tools_config(
if function_tools:
gemini_tools.append(types.Tool(function_declarations=function_tools))

# Some Google LLMs do not support multiple tool types (either function tools or builtin tools).
if _only_single_type and gemini_tools:
provider_tools = [tool for tool in tool_ctx.provider_tools if isinstance(tool, GeminiTool)]
# generateContent only supports combining built-in tools with function tools
# on Gemini 3 models: https://ai.google.dev/gemini-api/docs/tool-combination
if function_tools and provider_tools and not allow_mixed_tools:
logger.warning(
"this model does not support combining provider tools with function tools; "
"ignoring provider tools (combining them requires a Gemini 3 model)"
)
return gemini_tools

for tool in tool_ctx.provider_tools:
if isinstance(tool, GeminiTool):
gemini_tools.append(tool.to_tool_config())

# only convert tools we actually send, so a dropped tool can't break the request
gemini_tools.extend(tool.to_tool_config() for tool in provider_tools)
return gemini_tools


Expand Down
2 changes: 1 addition & 1 deletion livekit-plugins/livekit-plugins-google/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ dependencies = [
"google-auth >= 2, < 3",
"google-cloud-speech >= 2, < 3",
"google-cloud-texttospeech >= 2.32, < 3",
"google-genai >= 1.67; python_version >= '3.10'",
"google-genai >= 1.68; python_version >= '3.10'",
"livekit-agents>=1.6.5",
]

Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading