Files
google--adk-python/tests/unittests/examples/test_example_util.py
T
wehub-resource-sync ec2b666284
Continuous Integration / Pre-commit Linter (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.10) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.11) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.12) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.12) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.14) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.12) (push) Has been cancelled
Copybara PR Handler / close-imported-pr (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.14) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:25:13 +08:00

459 lines
14 KiB
Python

# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for example_util."""
from google.adk.examples import base_example_provider
from google.adk.examples import example
from google.adk.examples import example_util
from google.genai import types
import pytest
BASIC_INPUT = types.Content(role="user", parts=[types.Part(text="test_input")])
BASIC_OUTPUT = [
types.Content(role="model", parts=[types.Part(text="test_output")])
]
BASIC_EXAMPLE = example.Example(input=BASIC_INPUT, output=BASIC_OUTPUT)
class MockExampleProvider(base_example_provider.BaseExampleProvider):
"""Mocks an ExampleProvider object.
This class provides mock implementation of the get_examples() function,
allowing the user to test functions that rely on an ExampleProvider
without creating a real ExampleProvider class and check that the correct
inputs are being passed to it.
"""
def __init__(
self, test_examples: list[example.Example], test_query: str
) -> None:
"""Initializes a MockExampleProvider.
Args:
test_examples: The list of examples to be returned on a successful query.
test_query: The query necessary to return a correct output.
"""
self.test_examples = test_examples
self.test_query = test_query
def get_examples(self, query: str) -> list[example.Example]:
"""Mocks querying the ExampleProvider for examples.
Verifies the query is correct, and returns an empty list if not.
Args:
query: The query to check examples for.
"""
if query == self.test_query:
return self.test_examples
else:
return []
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_text_only_example_conversion(model):
"""Tests converting a text-only Example object to a string for use in a system instruction."""
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}test_output\n"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
assert (
example_util.convert_examples_to_text(
examples=[BASIC_EXAMPLE], model=model
)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_multi_part_text_example_conversion(model):
"""Tests converting an Example object with multiple text Parts to a string for use in a system instruction."""
output_content = [
types.Content(
role="model",
parts=[
types.Part(text="test_output_1"),
types.Part(text="test_output_2"),
types.Part(text="test_output_3"),
],
)
]
test_example = example.Example(input=BASIC_INPUT, output=output_content)
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}test_output_1\ntest_output_2\ntest_output_3\n"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
assert (
example_util.convert_examples_to_text(
examples=[test_example], model=model
)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_example_conversion_prefix_insertion(model):
"""Tests if user and model prefixes are properly alternated when converting an Example object to text for use in a system instruction."""
output_content = [
types.Content(role="model", parts=[types.Part(text="test_output_1")]),
types.Content(role="user", parts=[types.Part(text="test_output_2")]),
types.Content(role="model", parts=[types.Part(text="test_output_3")]),
]
test_example = example.Example(input=BASIC_INPUT, output=output_content)
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}test_output_1\n"
f"{example_util._USER_PREFIX}test_output_2\n"
f"{example_util._MODEL_PREFIX}test_output_3\n"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
assert (
example_util.convert_examples_to_text(
examples=[test_example], model=model
)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_example_conversion_output_clumping(model):
"""Tests whether user and model inputs are properly clumped when converting an Example object to text for use in a system instruction."""
output_content = [
types.Content(role="model", parts=[types.Part(text="test_output_1")]),
types.Content(role="model", parts=[types.Part(text="test_output_2")]),
types.Content(role="user", parts=[types.Part(text="test_output_3")]),
types.Content(role="user", parts=[types.Part(text="test_output_4")]),
]
test_example = example.Example(input=BASIC_INPUT, output=output_content)
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}test_output_1\ntest_output_2\n"
f"{example_util._USER_PREFIX}test_output_3\ntest_output_4\n"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
assert (
example_util.convert_examples_to_text(
examples=[test_example], model=model
)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_empty_examples_list_conversion(model):
"""Tests Example conversion to text if the examples list is empty."""
expected_output = (
f"{example_util._EXAMPLES_INTRO}{example_util._EXAMPLES_END}"
)
assert (
example_util.convert_examples_to_text(examples=[], model=model)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_example_conversion_with_function_call(model):
"""Tests converting an Example object containing a function call to a string for use in a system instruction."""
test_function_call = types.FunctionCall(
name="test_function",
args={"test_string_argument": "test_value", "test_int_argument": 1},
)
output_content = [
types.Content(
role="model", parts=[types.Part(function_call=test_function_call)]
)
]
test_example = example.Example(input=BASIC_INPUT, output=output_content)
gemini2 = model is None or "gemini-2" in model
prefix = (
example_util._FUNCTION_PREFIX
if gemini2
else example_util._FUNCTION_CALL_PREFIX
)
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}{prefix}"
"test_function(test_string_argument='test_value', test_int_argument=1)"
f"{example_util._FUNCTION_CALL_SUFFIX}"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
assert (
example_util.convert_examples_to_text(
examples=[test_example], model=model
)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_example_conversion_with_function_response(model):
"""Tests converting an Example object containing a function response to a string for use in a system instruction."""
test_function_response = types.FunctionResponse(
name="test_function",
response={"test_string_argument": "test_value", "test_int_argument": 1},
)
output_content = [
types.Content(
role="model",
parts=[types.Part(function_response=test_function_response)],
)
]
test_example = example.Example(input=BASIC_INPUT, output=output_content)
gemini2 = model is None or "gemini-2" in model
prefix = (
example_util._FUNCTION_PREFIX
if gemini2
else example_util._FUNCTION_RESPONSE_PREFIX
)
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}{prefix}"
f"{test_function_response.__dict__}"
f"{example_util._FUNCTION_RESPONSE_SUFFIX}"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
assert (
example_util.convert_examples_to_text(
examples=[test_example], model=model
)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_example_conversion_with_function_call_response(model):
"""Tests converting an Example object containing a function call and response to a string for use in a system instruction."""
test_function_call = types.FunctionCall(
name="test_function",
args={"test_string_argument": "test_value", "test_int_argument": 1},
)
test_function_response = types.FunctionResponse(
name="test_function",
response={"test_string_argument": "test_value", "test_int_argument": 1},
)
output_content = [
types.Content(
role="model",
parts=[
types.Part(function_call=test_function_call),
types.Part(function_response=test_function_response),
],
)
]
test_example = example.Example(input=BASIC_INPUT, output=output_content)
gemini2 = model is None or "gemini-2" in model
response_prefix = (
example_util._FUNCTION_PREFIX
if gemini2
else example_util._FUNCTION_RESPONSE_PREFIX
)
call_prefix = (
example_util._FUNCTION_PREFIX
if gemini2
else example_util._FUNCTION_CALL_PREFIX
)
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}{call_prefix}"
"test_function(test_string_argument='test_value', test_int_argument=1)"
f"{example_util._FUNCTION_CALL_SUFFIX}"
f"{response_prefix}"
f"{test_function_response.__dict__}"
f"{example_util._FUNCTION_RESPONSE_SUFFIX}"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
assert (
example_util.convert_examples_to_text(
examples=[test_example], model=model
)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_example_conversion_with_text_and_function_call_response(model):
"""Tests converting an Example object containing text, a function call, and a function response to a string for use in a system instruction."""
test_function_call = types.FunctionCall(
name="test_function",
args={"test_string_argument": "test_value", "test_int_argument": 1},
)
test_function_response = types.FunctionResponse(
name="test_function",
response={"test_string_argument": "test_value", "test_int_argument": 1},
)
output_content = [
types.Content(
role="model",
parts=[
types.Part(text="test_output"),
types.Part(function_call=test_function_call),
types.Part(function_response=test_function_response),
],
)
]
test_example = example.Example(input=BASIC_INPUT, output=output_content)
gemini2 = model is None or "gemini-2" in model
response_prefix = (
example_util._FUNCTION_PREFIX
if gemini2
else example_util._FUNCTION_RESPONSE_PREFIX
)
call_prefix = (
example_util._FUNCTION_PREFIX
if gemini2
else example_util._FUNCTION_CALL_PREFIX
)
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}test_output\n"
f"{call_prefix}"
"test_function(test_string_argument='test_value', test_int_argument=1)"
f"{example_util._FUNCTION_CALL_SUFFIX}"
f"{response_prefix}"
f"{test_function_response.__dict__}"
f"{example_util._FUNCTION_RESPONSE_SUFFIX}"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
assert (
example_util.convert_examples_to_text(
examples=[test_example], model=model
)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_building_si_from_list(model):
"""Tests building System Information from a list of examples."""
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}test_output\n"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
assert (
example_util.build_example_si(
examples=[BASIC_EXAMPLE], query="", model=model
)
== expected_output
)
@pytest.mark.parametrize(
"model",
["gemini-2.5-flash", "llama3_vertex_agent", None],
)
def test_building_si_from_base_example_provider(model):
"""Tests building System Information from an example provider."""
expected_output = (
f"{example_util._EXAMPLES_INTRO}"
f"{example_util._EXAMPLE_START.format(1)}"
f"{example_util._USER_PREFIX}test_input\n"
f"{example_util._MODEL_PREFIX}test_output\n"
f"{example_util._EXAMPLE_END}"
f"{example_util._EXAMPLES_END}"
)
example_provider = MockExampleProvider(
test_examples=[BASIC_EXAMPLE], test_query="test_query"
)
assert (
example_util.build_example_si(
examples=example_provider, query="test_query", model=model
)
== expected_output
)