mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-05 10:24:03 +00:00
Revert "fix(vertex): skip harmful schema transforms for Gemini 2.0+ tool parameters"
This reverts commit a9c3095cc5.
This commit is contained in:
@@ -520,28 +520,6 @@ def _build_vertex_schema(parameters: dict, add_property_ordering: bool = False):
|
||||
return parameters
|
||||
|
||||
|
||||
def _build_vertex_schema_for_gemini_2(parameters: dict) -> dict:
|
||||
"""
|
||||
Minimal schema builder for Gemini 2.0+ tool parameters.
|
||||
|
||||
Gemini 2.0+ accepts standard JSON Schema natively in tool parameters,
|
||||
including lowercase types, anyOf with null, and bare {} (TYPE_UNSPECIFIED).
|
||||
The only transformation needed is resolving $ref/$defs, which Gemini does
|
||||
NOT support in tool parameters (returns 400).
|
||||
|
||||
This avoids the harmful transforms in _build_vertex_schema that break
|
||||
JsonValue/Any semantics by coercing {} to {"type": "object"}.
|
||||
"""
|
||||
valid_schema_fields = set(get_type_hints(Schema).keys())
|
||||
|
||||
defs = parameters.pop("$defs", {})
|
||||
unpack_defs(parameters, defs)
|
||||
|
||||
parameters = filter_schema_fields(parameters, valid_schema_fields)
|
||||
|
||||
return parameters
|
||||
|
||||
|
||||
def _build_json_schema(parameters: dict) -> dict:
|
||||
"""
|
||||
Build a JSON Schema for use with Gemini's responseJsonSchema parameter.
|
||||
|
||||
@@ -97,7 +97,6 @@ from ..common_utils import (
|
||||
VertexAIError,
|
||||
_build_json_schema,
|
||||
_build_vertex_schema,
|
||||
_build_vertex_schema_for_gemini_2,
|
||||
supports_response_json_schema,
|
||||
)
|
||||
from ..vertex_llm_base import VertexBase
|
||||
@@ -468,7 +467,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
||||
return None
|
||||
|
||||
def _map_function( # noqa: PLR0915
|
||||
self, value: List[dict], optional_params: dict, model: str = ""
|
||||
self, value: List[dict], optional_params: dict
|
||||
) -> List[Tools]:
|
||||
"""
|
||||
Map OpenAI-style tools/functions to Vertex AI format.
|
||||
@@ -511,21 +510,10 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
||||
"parameters" in _openai_function_object
|
||||
and _openai_function_object["parameters"] is not None
|
||||
and isinstance(_openai_function_object["parameters"], dict)
|
||||
):
|
||||
if supports_response_json_schema(model):
|
||||
# Gemini 2.0+: minimal transform (resolve $ref only)
|
||||
_openai_function_object["parameters"] = (
|
||||
_build_vertex_schema_for_gemini_2(
|
||||
_openai_function_object["parameters"]
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Gemini 1.5: full OpenAPI-style transform
|
||||
_openai_function_object["parameters"] = (
|
||||
_build_vertex_schema(
|
||||
_openai_function_object["parameters"]
|
||||
)
|
||||
)
|
||||
): # OPENAI accepts JSON Schema, Google accepts OpenAPI schema.
|
||||
_openai_function_object["parameters"] = _build_vertex_schema(
|
||||
_openai_function_object["parameters"]
|
||||
)
|
||||
|
||||
openai_function_object = _openai_function_object
|
||||
|
||||
@@ -1063,7 +1051,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
|
||||
):
|
||||
# Pass optional_params so _map_function can add toolConfig if needed
|
||||
mapped_tools = self._map_function(
|
||||
value=value, optional_params=optional_params, model=model
|
||||
value=value, optional_params=optional_params
|
||||
)
|
||||
optional_params = self._add_tools_to_optional_params(
|
||||
optional_params, mapped_tools
|
||||
|
||||
@@ -11,7 +11,6 @@ sys.path.insert(
|
||||
) # Adds the parent directory to the system path
|
||||
|
||||
from litellm.llms.vertex_ai.common_utils import (
|
||||
_build_vertex_schema_for_gemini_2,
|
||||
_get_vertex_url,
|
||||
convert_anyof_null_to_nullable,
|
||||
get_vertex_location_from_url,
|
||||
@@ -1403,93 +1402,3 @@ def test_add_object_type_does_not_add_type_when_anyof_present():
|
||||
|
||||
# Verify type was not added (anyOf handles the type)
|
||||
assert "type" not in input_schema, "type should not be added when anyOf is present"
|
||||
|
||||
|
||||
class TestBuildVertexSchemaForGemini2:
|
||||
"""Tests for _build_vertex_schema_for_gemini_2 — minimal transform for Gemini 2.0+ tools."""
|
||||
|
||||
def test_jsonvalue_standalone_preserved(self):
|
||||
"""JsonValue (bare {}) should NOT be coerced to {"type": "object"}."""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"value": {},
|
||||
},
|
||||
"required": ["name", "value"],
|
||||
}
|
||||
result = _build_vertex_schema_for_gemini_2(schema)
|
||||
assert result["properties"]["value"] == {}
|
||||
|
||||
def test_optional_jsonvalue_anyof_preserved(self):
|
||||
"""Optional[JsonValue] anyOf with null should be preserved, not converted to nullable."""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"value": {
|
||||
"anyOf": [
|
||||
{"type": "array", "items": {}},
|
||||
{},
|
||||
{"type": "null"},
|
||||
]
|
||||
},
|
||||
},
|
||||
"required": ["name"],
|
||||
}
|
||||
result = _build_vertex_schema_for_gemini_2(schema)
|
||||
value_schema = result["properties"]["value"]
|
||||
assert "anyOf" in value_schema
|
||||
assert len(value_schema["anyOf"]) == 3
|
||||
assert {"type": "null"} in value_schema["anyOf"]
|
||||
assert {} in value_schema["anyOf"]
|
||||
|
||||
def test_ref_defs_resolved(self):
|
||||
"""$ref/$defs should be resolved since Gemini doesn't support them in tool params."""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"value": {"$ref": "#/$defs/JsonValue"},
|
||||
},
|
||||
"$defs": {"JsonValue": {}},
|
||||
}
|
||||
result = _build_vertex_schema_for_gemini_2(schema)
|
||||
assert "$ref" not in result["properties"]["value"]
|
||||
assert "$defs" not in result
|
||||
assert result["properties"]["value"] == {}
|
||||
|
||||
def test_unsupported_fields_stripped(self):
|
||||
"""Fields not in Vertex Schema TypedDict should be removed."""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string", "additionalProperties": False},
|
||||
},
|
||||
"additionalProperties": False,
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
}
|
||||
result = _build_vertex_schema_for_gemini_2(schema)
|
||||
assert "additionalProperties" not in result
|
||||
assert "$schema" not in result
|
||||
|
||||
def test_no_type_coercion(self):
|
||||
"""Schemas without type should NOT have type: object added."""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {"description": "Any data"},
|
||||
},
|
||||
}
|
||||
result = _build_vertex_schema_for_gemini_2(schema)
|
||||
assert "type" not in result["properties"]["data"]
|
||||
|
||||
def test_items_empty_preserved(self):
|
||||
"""items: {} should NOT be coerced to items: {"type": "object"}."""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"values": {"type": "array", "items": {}},
|
||||
},
|
||||
}
|
||||
result = _build_vertex_schema_for_gemini_2(schema)
|
||||
assert result["properties"]["values"]["items"] == {}
|
||||
|
||||
Reference in New Issue
Block a user