fix(gemini): Preserve non-ASCII characters in function call arguments (#16550)

Fixes #16533

Before this fix, non-ASCII characters (Japanese, Spanish, Chinese, etc.)
in function call arguments were being escaped as Unicode sequences.

Example:
- Before: "やあ" → "\u3084\u3042"
- After: "やあ" → "やあ" (preserved)

Changes:
- Add ensure_ascii=False to json.dumps() in _transform_parts()
- Add test for Japanese and Spanish Unicode character preservation

This is not a breaking change as both formats are equivalent in JSON.
The fix improves readability and aligns with OpenAI's behavior.
This commit is contained in:
Cesar Garcia 2025-11-13 00:01:38 -03:00 committed by GitHub
parent 018bd2e039
commit 049d45ea90
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 70 additions and 1 deletions

View file

@ -1022,7 +1022,7 @@ class VertexGeminiConfig(VertexAIBaseConfig, BaseConfig):
if "functionCall" in part:
_function_chunk = ChatCompletionToolCallFunctionChunk(
name=part["functionCall"]["name"],
arguments=json.dumps(part["functionCall"]["args"]),
arguments=json.dumps(part["functionCall"]["args"], ensure_ascii=False),
)
if is_function_call is True:
function = _function_chunk

View file

@ -1135,3 +1135,72 @@ def test_gemini_embedding():
)
print("response: ", response)
assert response is not None
def test_gemini_function_args_preserve_unicode():
"""
Test for Issue #16533: Gemini function call arguments should preserve non-ASCII characters
https://github.com/BerriAI/litellm/issues/16533
Before fix: "" becomes "\u3084"
After fix: "" stays as ""
"""
from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import VertexGeminiConfig
# Test Japanese characters
parts = [
{
"functionCall": {
"name": "send_message",
"args": {
"message": "やあ", # Japanese "hello"
"recipient": "たけし" # Japanese name
}
}
}
]
function, tools, _ = VertexGeminiConfig._transform_parts(
parts=parts,
cumulative_tool_call_idx=0,
is_function_call=False
)
arguments_str = tools[0]['function']['arguments']
parsed_args = json.loads(arguments_str)
# Verify characters are preserved
assert parsed_args["message"] == "やあ", "Japanese characters should be preserved"
assert parsed_args["recipient"] == "たけし", "Japanese characters should be preserved"
# Verify no Unicode escape sequences in raw string
assert "\\u" not in arguments_str, "Should not contain Unicode escape sequences"
assert "やあ" in arguments_str, "Original Japanese characters should be in the string"
assert "たけし" in arguments_str, "Original Japanese characters should be in the string"
# Test Spanish characters
parts_spanish = [
{
"functionCall": {
"name": "send_message",
"args": {
"message": "¡Hola! ¿Cómo estás?",
"recipient": "José"
}
}
}
]
function, tools, _ = VertexGeminiConfig._transform_parts(
parts=parts_spanish,
cumulative_tool_call_idx=0,
is_function_call=False
)
arguments_str = tools[0]['function']['arguments']
parsed_args = json.loads(arguments_str)
assert parsed_args["message"] == "¡Hola! ¿Cómo estás?"
assert parsed_args["recipient"] == "José"
assert "\\u" not in arguments_str
assert "José" in arguments_str