fix(gemini): send googleMaps retrievalConfig in the request body

VertexGeminiConfig._map_function extracts latitude/longitude from a
googleMaps tool into optional_params["toolConfig"]["retrievalConfig"],
but _transform_request_body only built toolConfig from tool_choice, so
the location never reached Google and Maps grounding ran without it

Pop toolConfig from optional_params and merge it with tool_choice.
Type retrievalConfig on ToolConfig
This commit is contained in:
Matt Trefilek 2026-08-27 11:18:46 -05:00
parent ca9007be39
commit 9e523dff45
3 changed files with 75 additions and 2 deletions

View file

@ -1191,6 +1191,7 @@ def _transform_request_body(
)
tools: Final[Tools | None] = optional_params.pop("tools", None)
tool_choice: Final[ToolConfig | None] = optional_params.pop("tool_choice", None)
tool_config: Final[ToolConfig | None] = optional_params.pop("toolConfig", None)
include_server_side_tool_invocations: bool = optional_params.pop("include_server_side_tool_invocations", False)
safety_settings: list[SafetSettingsConfig] | None = optional_params.pop("safety_settings", None)
# Drop output_config as it's not supported by Vertex AI
@ -1223,8 +1224,15 @@ def _transform_request_body(
data["system_instruction"] = system_instructions
if tools is not None:
data["tools"] = tools
if tool_choice is not None:
data["toolConfig"] = tool_choice
merged_tool_config: Final[ToolConfig | None] = (
{**tool_config, **tool_choice}
if tool_config is not None and tool_choice is not None
else tool_config
if tool_config is not None
else tool_choice
)
if merged_tool_config is not None:
data["toolConfig"] = merged_tool_config
if include_server_side_tool_invocations:
if "toolConfig" not in data:
data["toolConfig"] = {}

View file

@ -2,6 +2,7 @@ from enum import Enum
from typing import Any, Final, Literal, Protocol
from typing_extensions import (
ReadOnly,
Required,
TypedDict,
)
@ -278,9 +279,20 @@ class Tools(TypedDict, total=False):
retrieval: Retrieval
class LatLng(TypedDict):
latitude: ReadOnly[float]
longitude: ReadOnly[float]
class RetrievalConfig(TypedDict, total=False):
latLng: ReadOnly[LatLng]
languageCode: ReadOnly[str]
class ToolConfig(TypedDict, total=False):
functionCallingConfig: FunctionCallingConfig
includeServerSideToolInvocations: bool
retrievalConfig: ReadOnly[RetrievalConfig]
class TTL(TypedDict, total=False):

View file

@ -338,3 +338,56 @@ def test_map_function_enterprise_web_search_snake_case():
assert len(result) == 1
assert "enterpriseWebSearch" in result[0]
def test__transform_request_body_google_maps_retrieval_config_is_sent():
"""
googleMaps latitude/longitude are extracted into optional_params["toolConfig"]["retrievalConfig"]
by VertexGeminiConfig._map_function. That toolConfig must reach the request body, otherwise
Google grounds without a location.
"""
optional_params = {}
tools = VertexGeminiConfig()._map_function(
value=[{"googleMaps": {"latitude": 37.7749, "longitude": -122.4194}}],
optional_params=optional_params,
)
optional_params["tools"] = tools
rb: RequestBody = transformation._transform_request_body(
messages=[{"role": "user", "content": "coffee near me"}],
model="gemini-3-flash-preview",
optional_params=optional_params,
custom_llm_provider="gemini",
litellm_params={},
cached_content=None,
)
assert rb["tools"] == [{"googleMaps": {}}]
assert rb["toolConfig"] == {"retrievalConfig": {"latLng": {"latitude": 37.7749, "longitude": -122.4194}}}
def test__transform_request_body_tool_config_merges_with_tool_choice():
"""
A googleMaps retrievalConfig and a function-calling tool_choice both live under toolConfig;
neither should clobber the other.
"""
optional_params = {
"toolConfig": {"retrievalConfig": {"latLng": {"latitude": 1.0, "longitude": 2.0}}},
"tool_choice": {"functionCallingConfig": {"mode": "AUTO"}},
"include_server_side_tool_invocations": True,
}
rb: RequestBody = transformation._transform_request_body(
messages=[{"role": "user", "content": "hi"}],
model="gemini-3-flash-preview",
optional_params=optional_params,
custom_llm_provider="gemini",
litellm_params={},
cached_content=None,
)
assert rb["toolConfig"] == {
"retrievalConfig": {"latLng": {"latitude": 1.0, "longitude": 2.0}},
"functionCallingConfig": {"mode": "AUTO"},
"includeServerSideToolInvocations": True,
}