Fix Gemini API additionalProperties error (issue #2457)

Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
Devin AI
2025-03-24 11:32:29 +00:00
parent ed1f009c64
commit 3060c6f919
3 changed files with 61 additions and 2 deletions

View File

@@ -316,7 +316,19 @@ class LLM:
messages = [{"role": "user", "content": messages}]
formatted_messages = self._format_messages_for_provider(messages)
# --- 2) Prepare the parameters for the completion call
# --- 2) If using Gemini, ensure additionalProperties is not in tool schemas
if tools and "gemini" in self.model.lower():
for i, tool in enumerate(tools):
if (
isinstance(tool, dict)
and "function" in tool
and "parameters" in tool["function"]
):
params = tool["function"]["parameters"]
if "additionalProperties" in params:
del params["additionalProperties"]
# --- 3) Prepare the parameters for the completion call
params = {
"model": self.model,
"messages": formatted_messages,

View File

@@ -239,6 +239,26 @@ class CrewStructuredTool:
def args(self) -> dict:
"""Get the tool's input arguments schema."""
return self.args_schema.model_json_schema()["properties"]
def to_openai_function(self) -> dict:
"""Convert the tool to an OpenAI function format.
Returns:
dict: A dictionary in the OpenAI function format.
"""
schema = self.args_schema.model_json_schema()
# Remove additionalProperties field to prevent Gemini API errors
if "additionalProperties" in schema:
del schema["additionalProperties"]
return {
"type": "function",
"function": {
"name": self.name,
"description": self.description,
"parameters": schema
}
}
def __repr__(self) -> str:
return (

View File

@@ -25,7 +25,7 @@ def schema_class():
return TestSchema
class InternalCrewStructuredTool:
class TestInternalCrewStructuredTool:
def test_initialization(self, basic_function, schema_class):
"""Test basic initialization of CrewStructuredTool"""
tool = CrewStructuredTool(
@@ -144,3 +144,30 @@ class InternalCrewStructuredTool:
{"required_param": "test", "optional_param": "custom", "nullable_param": 42}
)
assert result == "test custom 42"
def test_to_openai_function_no_additional_properties(self):
"""Test that the to_openai_function method doesn't include additionalProperties."""
class TestSchema(BaseModel):
test_field: str = Field(..., description="A test field")
def test_func(test_field: str) -> str:
"""Test function that returns the input."""
return f"Test function received: {test_field}"
tool = CrewStructuredTool(
name="test_tool",
description="A test tool",
args_schema=TestSchema,
func=test_func
)
function_dict = tool.to_openai_function()
assert "additionalProperties" not in function_dict["function"]["parameters"]
# Verify other properties are correct
assert function_dict["type"] == "function"
assert function_dict["function"]["name"] == "test_tool"
assert function_dict["function"]["description"] == "A test tool"
assert "properties" in function_dict["function"]["parameters"]
assert "test_field" in function_dict["function"]["parameters"]["properties"]