Skip to content
Closed
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
3 changes: 3 additions & 0 deletions litellm/google_genai/adapters/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class _GenAIContentPart(TypedDict, total=False):
class _GenAIFunctionDeclaration(TypedDict, total=False):
name: ReadOnly[str]
description: ReadOnly[str]
parameters: ReadOnly[object]
parametersJsonSchema: ReadOnly[object]


Expand Down Expand Up @@ -392,6 +393,8 @@ def _transform_google_genai_tools_to_openai(
function_chunk["description"] = func_decl["description"]
if "parametersJsonSchema" in func_decl:
function_chunk["parameters"] = func_decl["parametersJsonSchema"]
elif "parameters" in func_decl:
function_chunk["parameters"] = func_decl["parameters"]
Comment on lines +396 to +397

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Provider logic outside standard hierarchy

This Google GenAI-specific branch extends provider behavior outside litellm/llms, increasing fragmentation and making future provider maintenance harder.

Rule Used: What: Avoid writing provider-specific code outside... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sits beside the existing parametersJsonSchema read in the same adapter. Relocating the bridge into litellm/llms is a separate refactor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point — the new elif is a one-liner that mirrors the existing parametersJsonSchema branch immediately above it, so it doesn't add new fragmentation. The adapter already lives outside litellm/llms, and relocating the whole bridge is a separate concern. The fix is correctly scoped.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.


openai_tool: _JsonDict = {"type": "function", "function": function_chunk}
openai_tools.append(openai_tool)
Expand Down
75 changes: 75 additions & 0 deletions tests/test_litellm/google_genai/test_google_genai_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1267,3 +1267,78 @@ def test_inline_data_backward_compatibility_text_only():
content, str
), "Content should be a string for text-only messages (backward compatibility)"
assert content == "Hello, how are you?"


def test_tools_transformation_parameters_field():
from litellm.google_genai.adapters.transformation import GoogleGenAIAdapter

adapter = GoogleGenAIAdapter()

schema = {
"type": "OBJECT",
"properties": {"city": {"type": "STRING", "description": "City name"}},
"required": ["city"],
}
tools = [
{
"functionDeclarations": [
{
"name": "get_weather",
"description": "Get the weather for a city",
"parameters": schema,
}
]
}
]

completion_request = adapter.translate_generate_content_to_completion(
model="gpt-3.5-turbo",
contents={"role": "user", "parts": [{"text": "Weather in Hanoi?"}]},
tools=tools,
)

function = completion_request["tools"][0]["function"]
assert function["name"] == "get_weather"
assert function["parameters"] == {
"type": "object",
"properties": {"city": {"type": "string", "description": "City name"}},
"required": ["city"],
}


def test_tools_transformation_prefers_parameters_json_schema():
from litellm.google_genai.adapters.transformation import GoogleGenAIAdapter

adapter = GoogleGenAIAdapter()

tools = [
{
"functionDeclarations": [
{
"name": "get_weather",
"parameters": {
"type": "OBJECT",
"properties": {"ignored": {"type": "STRING"}},
},
"parametersJsonSchema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}
]
}
]

completion_request = adapter.translate_generate_content_to_completion(
model="gpt-3.5-turbo",
contents={"role": "user", "parts": [{"text": "Weather in Hanoi?"}]},
tools=tools,
)

function = completion_request["tools"][0]["function"]
assert function["parameters"] == {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
}
Loading