fix: AttributeError and indentation in parameter processing. For issue #2776 and issue #2763

PiperOrigin-RevId: 804222317
This commit is contained in:
George Weale
2025-09-07 18:37:42 -07:00
committed by Copybara-Service
parent 1979dcf496
commit 1e23652968
2 changed files with 133 additions and 3 deletions
+6 -3
View File
@@ -392,7 +392,10 @@ def _function_declaration_to_tool_param(
},
}
if function_declaration.parameters.required:
if (
function_declaration.parameters
and function_declaration.parameters.required
):
tool_params["function"]["parameters"][
"required"
] = function_declaration.parameters.required
@@ -596,8 +599,8 @@ def _get_completion_inputs(
mapped_key = param_mapping.get(key, key)
generation_params[mapped_key] = config_dict[key]
if not generation_params:
generation_params = None
if not generation_params:
generation_params = None
return messages, tools, response_format, generation_params
+127
View File
@@ -731,6 +731,52 @@ function_declaration_test_cases = [
},
},
),
(
"no_parameters",
types.FunctionDeclaration(
name="test_function_no_params",
description="Test function with no parameters",
),
{
"type": "function",
"function": {
"name": "test_function_no_params",
"description": "Test function with no parameters",
"parameters": {
"type": "object",
"properties": {},
},
},
},
),
(
"parameters_without_required",
types.FunctionDeclaration(
name="test_function_no_required",
description="Test function with parameters but no required field",
parameters=types.Schema(
type=types.Type.OBJECT,
properties={
"optional_arg": types.Schema(type=types.Type.STRING),
},
),
),
{
"type": "function",
"function": {
"name": "test_function_no_required",
"description": (
"Test function with parameters but no required field"
),
"parameters": {
"type": "object",
"properties": {
"optional_arg": {"type": "string"},
},
},
},
},
),
]
@@ -1577,6 +1623,87 @@ def test_get_completion_inputs_generation_params():
assert "stop_sequences" not in generation_params
@pytest.mark.asyncio
def test_get_completion_inputs_empty_generation_params():
# Test that generation_params is None when no generation parameters are set
req = LlmRequest(
contents=[
types.Content(role="user", parts=[types.Part.from_text(text="hi")]),
],
config=types.GenerateContentConfig(),
)
from google.adk.models.lite_llm import _get_completion_inputs
_, _, _, generation_params = _get_completion_inputs(req)
assert generation_params is None
@pytest.mark.asyncio
def test_get_completion_inputs_minimal_config():
# Test that generation_params is None when config has no generation parameters
req = LlmRequest(
contents=[
types.Content(role="user", parts=[types.Part.from_text(text="hi")]),
],
config=types.GenerateContentConfig(
system_instruction="test instruction" # Non-generation parameter
),
)
from google.adk.models.lite_llm import _get_completion_inputs
_, _, _, generation_params = _get_completion_inputs(req)
assert generation_params is None
@pytest.mark.asyncio
def test_get_completion_inputs_partial_generation_params():
# Test that generation_params is correctly built even with only some parameters
req = LlmRequest(
contents=[
types.Content(role="user", parts=[types.Part.from_text(text="hi")]),
],
config=types.GenerateContentConfig(
temperature=0.7,
# Only temperature is set, others are None/default
),
)
from google.adk.models.lite_llm import _get_completion_inputs
_, _, _, generation_params = _get_completion_inputs(req)
assert generation_params is not None
assert generation_params["temperature"] == 0.7
# Should only contain the temperature parameter
assert len(generation_params) == 1
def test_function_declaration_to_tool_param_edge_cases():
"""Test edge cases for function declaration conversion that caused the original bug."""
from google.adk.models.lite_llm import _function_declaration_to_tool_param
# Test function with None parameters (the original bug scenario)
func_decl = types.FunctionDeclaration(
name="test_function_none_params",
description="Function with None parameters",
parameters=None,
)
result = _function_declaration_to_tool_param(func_decl)
expected = {
"type": "function",
"function": {
"name": "test_function_none_params",
"description": "Function with None parameters",
"parameters": {
"type": "object",
"properties": {},
},
},
}
assert result == expected
# Verify no 'required' field is added when parameters is None
assert "required" not in result["function"]["parameters"]
def test_gemini_via_litellm_warning(monkeypatch):
"""Test that Gemini via LiteLLM shows warning."""
# Ensure environment variable is not set