fix: Prevent escaping of Latin characters in LLM response

Merge https://github.com/google/adk-python/pull/2937

**Closes #2936**

This Pull Request addresses the issue where `LlmAgent` outputs, when configured with `output_schema` and `tools`, were presenting escaped Latin characters (e.g., `\xf3` for `ó`) in the final response. This behavior occurred because `json.dumps` was being called with `ensure_ascii=True` (its default), which is not ideal for human-readable output, especially when dealing with non-ASCII characters common in many languages like Portuguese.

**Changes Proposed:**

* Modified the `_OutputSchemaRequestProcessor` in `src/google/adk/flows/llm_flows/_output_schema_processor.py` to explicitly set `ensure_ascii=False` when calling `json.dumps` for the `set_model_response` tool's output.

**Impact:**

This change ensures that all non-ASCII characters in the structured model response are preserved in their natural form, improving the readability and user experience of agent outputs, particularly for users interacting in languages with accented characters or other special symbols.

**Testing:**

The fix was verified locally by running an `LlmAgent` with an `output_schema` and confirming that responses containing Latin characters (e.g., "ação", "caminhão", "ícone") are now correctly displayed without escaping.

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2937 from amenegola:fix/issue-2936-escape-chars 6cac00f97aa4cd8d8ccaa97ec5fffc74f57995dc
PiperOrigin-RevId: 808622892
This commit is contained in:
Afonso Menegola
2025-09-18 09:47:28 -07:00
committed by Copybara-Service
parent 86ee6e3fa3
commit c9ea80af28
2 changed files with 34 additions and 1 deletions
@@ -107,7 +107,7 @@ def get_structured_model_response(function_response_event: Event) -> str | None:
for func_response in function_response_event.get_function_responses():
if func_response.name == 'set_model_response':
# Convert dict to JSON string
return json.dumps(func_response.response)
return json.dumps(func_response.response, ensure_ascii=False)
return None
@@ -254,6 +254,39 @@ async def test_output_schema_helper_functions():
assert extracted_json is None
@pytest.mark.asyncio
async def test_get_structured_model_response_with_non_ascii():
"""Test get_structured_model_response with non-ASCII characters."""
from google.adk.events.event import Event
from google.adk.flows.llm_flows._output_schema_processor import get_structured_model_response
from google.genai import types
# Test with a dictionary containing non-ASCII characters
test_dict = {'city': 'São Paulo'}
expected_json = '{"city": "São Paulo"}'
# Create a function response event
function_response_event = Event(
author='test_agent',
content=types.Content(
role='user',
parts=[
types.Part(
function_response=types.FunctionResponse(
name='set_model_response', response=test_dict
)
)
],
),
)
# Get the structured response
extracted_json = get_structured_model_response(function_response_event)
# Assert that the output is the expected JSON string without escaped characters
assert extracted_json == expected_json
@pytest.mark.asyncio
async def test_end_to_end_integration():
"""Test the complete output schema with tools integration."""