Skip to content
Merged
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
2 changes: 1 addition & 1 deletion litellm/llms/vertex_ai/gemini/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ def _transform_request_body(
# as "labels" field to the request sent to the Gemini backend.
if labels is None and "metadata" in litellm_params:
metadata = litellm_params["metadata"]
if "requester_metadata" in metadata:
if metadata is not None and "requester_metadata" in metadata:
rm = metadata["requester_metadata"]
labels = {k: v for k, v in rm.items() if type(v) is str}

Expand Down
2 changes: 2 additions & 0 deletions litellm/model_prices_and_context_window_backup.json
Original file line number Diff line number Diff line change
Expand Up @@ -11963,6 +11963,7 @@
"supports_vision": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_function_calling": true,
"supports_reasoning": true
},
"openai.gpt-oss-120b-1:0": {
Expand All @@ -11977,6 +11978,7 @@
"supports_vision": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_function_calling": true,
"supports_reasoning": true
},
"anthropic.claude-opus-4-1-20250805-v1:0": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,81 +1,9 @@
from litellm.llms.vertex_ai.gemini.transformation import (
check_if_part_exists_in_parts,
_transform_request_body,
)


def test_check_if_part_exists_in_parts():
parts = [
{"text": "Hello", "thought": True},
{"text": "World", "thought": False},
]
part = {"text": "Hello", "thought": True}
new_part = {"text": "Hello World", "thought": True}
assert check_if_part_exists_in_parts(parts, part)
assert not check_if_part_exists_in_parts(parts, new_part, ["thought"])
assert check_if_part_exists_in_parts(parts, new_part, ["text"])


def test_check_if_part_exists_in_parts_camel_case_snake_case():
"""Test that function handles both camelCase and snake_case key variations"""
# Test snake_case to camelCase matching
parts_with_snake_case = [
{
"function_call": {
"name": "get_current_weather",
"args": {"location": "San Francisco, CA"},
}
},
{"text": "Some other content"},
]

part_with_camel_case = {
"functionCall": {
"name": "get_current_weather",
"args": {"location": "San Francisco, CA"},
}
}

# Should find match between function_call and functionCall
assert check_if_part_exists_in_parts(parts_with_snake_case, part_with_camel_case)

# Test camelCase to snake_case matching
parts_with_camel_case = [
{"functionCall": {"name": "calculate_sum", "args": {"a": 1, "b": 2}}}
]

part_with_snake_case = {
"function_call": {"name": "calculate_sum", "args": {"a": 1, "b": 2}}
}

# Should find match between functionCall and function_call
assert check_if_part_exists_in_parts(parts_with_camel_case, part_with_snake_case)

# Test no match when values differ
part_with_different_values = {
"function_call": {"name": "different_function", "args": {"x": 5}}
}

assert not check_if_part_exists_in_parts(
parts_with_snake_case, part_with_different_values
)

# Test multiple keys with mixed casing
parts_mixed = [
{
"function_call": {"name": "test"},
"thoughtSignature": "reasoning",
"text": "content",
}
]

part_mixed_casing = {
"functionCall": {"name": "test"},
"thought_signature": "reasoning",
"text": "content",
}

assert check_if_part_exists_in_parts(parts_mixed, part_mixed_casing)
# Tests for check_if_part_exists_in_parts removed - function not yet in carto/main
# Will be re-added when upstream-sync-resolver/24 is merged


# Tests for issue #14556: Labels field provider-aware filtering
Expand Down