chore: Removes LlmAgent.examples field, which was already abandoned before 0.1 version

For context: tools/example_tool.py was created to replace LlmAgent.example

Also removes relevant usage in tests.

PiperOrigin-RevId: 768193042
This commit is contained in:
Wei Sun (Jack)
2025-06-06 13:17:10 -07:00
committed by Copybara-Service
parent 309a656f49
commit a09781142a
4 changed files with 0 additions and 323 deletions
-5
View File
@@ -204,11 +204,6 @@ class LlmAgent(BaseAgent):
"""
# Advance features - End
# TODO: remove below fields after migration. - Start
# These fields are added back for easier migration.
examples: Optional[ExamplesUnion] = None
# TODO: remove above fields after migration. - End
# Callbacks - Start
before_model_callback: Optional[BeforeModelCallback] = None
"""Callback or list of callbacks to be called before calling the LLM.
@@ -1,15 +0,0 @@
# Copyright 2025 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.
from . import agent
@@ -1,161 +0,0 @@
# Copyright 2025 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.
from google.adk import Agent
from google.adk.examples import Example
from google.adk.sessions import Session
from google.genai import types
def reset_data():
pass
def fetch_user_flight_information(customer_email: str) -> str:
"""Fetch user flight information."""
return """
[{"ticket_no": "7240005432906569", "book_ref": "C46E9F", "flight_id": 19250, "flight_no": "LX0112", "departure_airport": "CDG", "arrival_airport": "BSL", "scheduled_departure": "2024-12-30 12:09:03.561731-04:00", "scheduled_arrival": "2024-12-30 13:39:03.561731-04:00", "seat_no": "18E", "fare_conditions": "Economy"}]
"""
def list_customer_flights(customer_email: str) -> str:
return "{'flights': [{'book_ref': 'C46E9F'}]}"
def update_ticket_to_new_flight(ticket_no: str, new_flight_id: str) -> str:
return 'OK, your ticket has been updated.'
def lookup_company_policy(topic: str) -> str:
"""Lookup policies for flight cancelation and rebooking."""
return """
1. How can I change my booking?
* The ticket number must start with 724 (SWISS ticket no./plate).
* The ticket was not paid for by barter or voucher (there are exceptions to voucher payments; if the ticket was paid for in full by voucher, then it may be possible to rebook online under certain circumstances. If it is not possible to rebook online because of the payment method, then you will be informed accordingly during the rebooking process).
* There must be an active flight booking for your ticket. It is not possible to rebook open tickets or tickets without the corresponding flight segments online at the moment.
* It is currently only possible to rebook outbound (one-way) tickets or return tickets with single flight routes (point-to-point).
"""
def search_flights(
departure_airport: str = None,
arrival_airport: str = None,
start_time: str = None,
end_time: str = None,
) -> list[dict]:
return """
[{"flight_id": 19238, "flight_no": "LX0112", "scheduled_departure": "2024-05-08 12:09:03.561731-04:00", "scheduled_arrival": "2024-05-08 13:39:03.561731-04:00", "departure_airport": "CDG", "arrival_airport": "BSL", "status": "Scheduled", "aircraft_code": "SU9", "actual_departure": null, "actual_arrival": null}, {"flight_id": 19242, "flight_no": "LX0112", "scheduled_departure": "2024-05-09 12:09:03.561731-04:00", "scheduled_arrival": "2024-05-09 13:39:03.561731-04:00", "departure_airport": "CDG", "arrival_airport": "BSL", "status": "Scheduled", "aircraft_code": "SU9", "actual_departure": null, "actual_arrival": null}]"""
def search_hotels(
location: str = None,
price_tier: str = None,
checkin_date: str = None,
checkout_date: str = None,
) -> list[dict]:
return """
[{"id": 1, "name": "Hilton Basel", "location": "Basel", "price_tier": "Luxury"}, {"id": 3, "name": "Hyatt Regency Basel", "location": "Basel", "price_tier": "Upper Upscale"}, {"id": 8, "name": "Holiday Inn Basel", "location": "Basel", "price_tier": "Upper Midscale"}]
"""
def book_hotel(hotel_name: str) -> str:
return 'OK, your hotel has been booked.'
def before_model_call(agent: Agent, session: Session, user_message):
if 'expedia' in user_message.lower():
response = types.Content(
role='model',
parts=[types.Part(text="Sorry, I can't answer this question.")],
)
return response
return None
def after_model_call(
agent: Agent, session: Session, content: types.Content
) -> bool:
model_message = content.parts[0].text
if 'expedia' in model_message.lower():
response = types.Content(
role='model',
parts=[types.Part(text="Sorry, I can't answer this question.")],
)
return response
return None
flight_agent = Agent(
model='gemini-1.5-pro',
name='flight_agent',
description='Handles flight information, policy and updates',
instruction="""
You are a specialized assistant for handling flight updates.
The primary assistant delegates work to you whenever the user needs help updating their bookings.
Confirm the updated flight details with the customer and inform them of any additional fees.
When searching, be persistent. Expand your query bounds if the first search returns no results.
Remember that a booking isn't completed until after the relevant tool has successfully been used.
Do not waste the user's time. Do not make up invalid tools or functions.
""",
tools=[
list_customer_flights,
lookup_company_policy,
fetch_user_flight_information,
search_flights,
update_ticket_to_new_flight,
],
)
hotel_agent = Agent(
model='gemini-1.5-pro',
name='hotel_agent',
description='Handles hotel information and booking',
instruction="""
You are a specialized assistant for handling hotel bookings.
The primary assistant delegates work to you whenever the user needs help booking a hotel.
Search for available hotels based on the user's preferences and confirm the booking details with the customer.
When searching, be persistent. Expand your query bounds if the first search returns no results.
""",
tools=[search_hotels, book_hotel],
)
root_agent = Agent(
model='gemini-1.5-pro',
name='root_agent',
instruction="""
You are a helpful customer support assistant for Swiss Airlines.
""",
sub_agents=[flight_agent, hotel_agent],
flow='auto',
examples=[
Example(
input=types.Content(
role='user',
parts=[types.Part(text='How were you built?')],
),
output=[
types.Content(
role='model',
parts=[
types.Part(
text='I was built with the best agent framework.'
)
],
)
],
),
],
)
@@ -1,142 +0,0 @@
# Copyright 2025 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.
# TODO: delete and rewrite unit tests
from google.adk.agents import Agent
from google.adk.examples import BaseExampleProvider
from google.adk.examples import Example
from google.adk.flows.llm_flows import examples
from google.adk.models.base_llm import LlmRequest
from google.genai import types
import pytest
from ... import testing_utils
@pytest.mark.asyncio
async def test_no_examples():
request = LlmRequest(
model="gemini-1.5-flash",
config=types.GenerateContentConfig(system_instruction=""),
)
agent = Agent(model="gemini-1.5-flash", name="agent", examples=[])
invocation_context = await testing_utils.create_invocation_context(
agent=agent, user_content=""
)
async for _ in examples.request_processor.run_async(
invocation_context,
request,
):
pass
assert request.config.system_instruction == ""
@pytest.mark.asyncio
async def test_agent_examples():
example_list = [
Example(
input=types.Content(
role="user",
parts=[types.Part.from_text(text="test1")],
),
output=[
types.Content(
role="model",
parts=[types.Part.from_text(text="response1")],
),
],
)
]
request = LlmRequest(
model="gemini-1.5-flash",
config=types.GenerateContentConfig(system_instruction=""),
)
agent = Agent(
model="gemini-1.5-flash",
name="agent",
examples=example_list,
)
invocation_context = await testing_utils.create_invocation_context(
agent=agent, user_content="test"
)
async for _ in examples.request_processor.run_async(
invocation_context,
request,
):
pass
assert (
request.config.system_instruction
== "<EXAMPLES>\nBegin few-shot\nThe following are examples of user"
" queries and model responses using the available tools.\n\nEXAMPLE"
" 1:\nBegin example\n[user]\ntest1\n\n[model]\nresponse1\nEnd"
" example\n\nEnd few-shot\nNow, try to follow these examples and"
" complete the following conversation\n<EXAMPLES>"
)
@pytest.mark.asyncio
async def test_agent_base_example_provider():
class TestExampleProvider(BaseExampleProvider):
def get_examples(self, query: str) -> list[Example]:
if query == "test":
return [
Example(
input=types.Content(
role="user",
parts=[types.Part.from_text(text="test")],
),
output=[
types.Content(
role="model",
parts=[types.Part.from_text(text="response1")],
),
],
)
]
else:
return []
provider = TestExampleProvider()
request = LlmRequest(
model="gemini-1.5-flash",
config=types.GenerateContentConfig(system_instruction=""),
)
agent = Agent(
model="gemini-1.5-flash",
name="agent",
examples=provider,
)
invocation_context = await testing_utils.create_invocation_context(
agent=agent, user_content="test"
)
async for _ in examples.request_processor.run_async(
invocation_context,
request,
):
pass
assert (
request.config.system_instruction
== "<EXAMPLES>\nBegin few-shot\nThe following are examples of user"
" queries and model responses using the available tools.\n\nEXAMPLE"
" 1:\nBegin example\n[user]\ntest\n\n[model]\nresponse1\nEnd"
" example\n\nEnd few-shot\nNow, try to follow these examples and"
" complete the following conversation\n<EXAMPLES>"
)