From 26fe53aceed0f2d33ea275b3a5eac347002580de Mon Sep 17 00:00:00 2001 From: Pierre Date: Wed, 5 Feb 2025 11:34:01 +0100 Subject: [PATCH 1/4] add examples 02 with tools --- README.md | 6 +- examples/02_agent_with_tools.py | 102 ++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 examples/02_agent_with_tools.py diff --git a/README.md b/README.md index 026bf58..d988fea 100644 --- a/README.md +++ b/README.md @@ -419,8 +419,8 @@ Tools allow enhancing an agent's capabilities by allowing it to call external fu WorkflowAI hosts a few tools: -- `@browser-text` allows fetching the content of a web page -- `@search` allows performing a web search +- `@browser-text` allows fetching the text content of a web page +- `@search-google` allows performing a web search Hosted tools tend to be faster because there is no back and forth between the client and the WorkflowAI API. Instead, if a tool call is needed, the WorkflowAI API will call it within a single request. @@ -433,7 +433,7 @@ To use a tool, simply add it's handles to the instructions (the function docstri @workflowai.agent() async def analyze_call_feedback(input: CallFeedbackInput) -> CallFeedbackOutput: """ - You can use @search and @browser-text to retrieve information about the name. + You can use @search-google and @browser-text to retrieve information about the name. """ ... ``` diff --git a/examples/02_agent_with_tools.py b/examples/02_agent_with_tools.py new file mode 100644 index 0000000..401c55f --- /dev/null +++ b/examples/02_agent_with_tools.py @@ -0,0 +1,102 @@ +""" +This example demonstrates how to use tools with WorkflowAI agents: +1. Built-in tools like @search-google +2. Custom tools (getting today's date and calculating days between dates) +3. Handling tool responses in the agent +""" + +import asyncio +from datetime import date, datetime +from typing import Annotated + +from pydantic import BaseModel, Field + +import workflowai +from workflowai import Model, Run + + +def get_current_date() -> str: + """Return today's date in ISO format (YYYY-MM-DD)""" + return datetime.now().date().isoformat() + + +def calculate_days_between( + date1: Annotated[str, "First date in YYYY-MM-DD format"], + date2: Annotated[str, "Second date in YYYY-MM-DD format"], +) -> int: + """Calculate the number of days between two dates.""" + d1 = date.fromisoformat(date1) + d2 = date.fromisoformat(date2) + return abs((d2 - d1).days) + + +class EventInput(BaseModel): + """Input for finding information about an event.""" + query: str = Field( + description="The event to get information about", + examples=["When was the first iPhone released?", "Who won the 2022 World Cup?"], + ) + + +class EventOutput(BaseModel): + """Output containing event information and context.""" + event_date: str = Field( + description="The date when the event occurred", + examples=["2007-06-29", "2022-12-18"], + ) + description: str = Field( + description="Description of the event", + ) + days_since: int = Field( + description="Number of days between the event and today", + ) + source: str = Field( + description="Source of the information", + ) + + +@workflowai.agent( + id="event-analyzer", + model=Model.GEMINI_1_5_FLASH_LATEST, + tools=[get_current_date, calculate_days_between], +) +async def analyze_event(query: EventInput) -> Run[EventOutput]: + """ + Find information about historical events and calculate days since they occurred. + + You have access to these tools: + 1. @search-google - Use this to find accurate information about events + 2. get_current_date - Use this to get today's date for calculating days since the event + 3. calculate_days_between - Calculate days between two dates (format: YYYY-MM-DD) + + Guidelines: + 1. Use @search-google to find accurate event information + 2. Get today's date using the get_current_date tool + 3. Use calculate_days_between with the event date and current date to get days_since + 4. Include the source of information (website URL) + 5. Be precise with dates and calculations + 6. Make sure dates are in YYYY-MM-DD format when using tools + """ + ... + + +async def main(): + # Example 1: Recent tech launch event + print("\nExample 1: Latest iPhone Launch") + print("-" * 50) + result = await analyze_event(EventInput(query="When was the latest iPhone launched?")) + print(result.output) + print(f"Cost: ${result.cost_usd}") + print(f"Latency: {result.duration_seconds:.2f}s") + + # Example 2: Recent space exploration event + print("\nExample 2: SpaceX Starship Launch") + print("-" * 50) + result = await analyze_event(EventInput(query="When was the latest SpaceX Starship test flight?")) + print(result.output) + print(f"Cost: ${result.cost_usd}") + print(f"Latency: {result.duration_seconds:.2f}s") + + +if __name__ == "__main__": + asyncio.run(main()) From f8cd102930bb6e41c7e198c0b4f6e7f09e5af638 Mon Sep 17 00:00:00 2001 From: Pierre Date: Wed, 5 Feb 2025 19:12:26 +0100 Subject: [PATCH 2/4] fix ruff errors --- examples/02_agent_with_tools.py | 90 ++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/examples/02_agent_with_tools.py b/examples/02_agent_with_tools.py index 401c55f..08aea50 100644 --- a/examples/02_agent_with_tools.py +++ b/examples/02_agent_with_tools.py @@ -1,15 +1,17 @@ """ -This example demonstrates how to use tools with WorkflowAI agents: -1. Built-in tools like @search-google -2. Custom tools (getting today's date and calculating days between dates) -3. Handling tool responses in the agent +This example demonstrates how to create a WorkflowAI agent that uses tools to enhance its capabilities. +It showcases: + +1. Using built-in WorkflowAI tools (@search-google) +2. Creating and using custom tools +3. Combining multiple tools in a single agent """ import asyncio from datetime import date, datetime -from typing import Annotated from pydantic import BaseModel, Field +from zoneinfo import ZoneInfo import workflowai from workflowai import Model, Run @@ -17,83 +19,91 @@ def get_current_date() -> str: """Return today's date in ISO format (YYYY-MM-DD)""" - return datetime.now().date().isoformat() + return datetime.now(tz=ZoneInfo("UTC")).date().isoformat() -def calculate_days_between( - date1: Annotated[str, "First date in YYYY-MM-DD format"], - date2: Annotated[str, "Second date in YYYY-MM-DD format"], -) -> int: - """Calculate the number of days between two dates.""" +def calculate_days_between(date1: str, date2: str) -> int: + """Calculate the number of days between two dates in ISO format (YYYY-MM-DD)""" d1 = date.fromisoformat(date1) d2 = date.fromisoformat(date2) return abs((d2 - d1).days) -class EventInput(BaseModel): - """Input for finding information about an event.""" +class HistoricalEventInput(BaseModel): + """Input model for querying historical events.""" query: str = Field( - description="The event to get information about", - examples=["When was the first iPhone released?", "Who won the 2022 World Cup?"], + description="A query about a historical event", + examples=[ + "When was the first moon landing?", + "When did World War II end?", + "When was the Declaration of Independence signed?", + ], ) -class EventOutput(BaseModel): - """Output containing event information and context.""" +class HistoricalEventOutput(BaseModel): + """Output model containing information about a historical event.""" event_date: str = Field( - description="The date when the event occurred", - examples=["2007-06-29", "2022-12-18"], + description="The date of the event in ISO format (YYYY-MM-DD)", + examples=["1969-07-20", "1945-09-02", "1776-07-04"], ) - description: str = Field( - description="Description of the event", + event_description: str = Field( + description="A brief description of the event", + examples=[ + "Apollo 11 astronauts Neil Armstrong and Buzz Aldrin became the first humans to land on the Moon", + "Japan formally surrendered to the Allied Powers aboard the USS Missouri in Tokyo Bay", + ], ) - days_since: int = Field( + days_since_event: int = Field( description="Number of days between the event and today", - ) - source: str = Field( - description="Source of the information", + examples=[19876, 28490, 90123], ) @workflowai.agent( - id="event-analyzer", + id="historical-event-analyzer", model=Model.GEMINI_1_5_FLASH_LATEST, tools=[get_current_date, calculate_days_between], ) -async def analyze_event(query: EventInput) -> Run[EventOutput]: +async def analyze_historical_event(event_input: HistoricalEventInput) -> Run[HistoricalEventOutput]: """ Find information about historical events and calculate days since they occurred. - + You have access to these tools: 1. @search-google - Use this to find accurate information about events 2. get_current_date - Use this to get today's date for calculating days since the event 3. calculate_days_between - Calculate days between two dates (format: YYYY-MM-DD) - + Guidelines: 1. Use @search-google to find accurate event information - 2. Get today's date using the get_current_date tool - 3. Use calculate_days_between with the event date and current date to get days_since - 4. Include the source of information (website URL) - 5. Be precise with dates and calculations - 6. Make sure dates are in YYYY-MM-DD format when using tools + 2. Use get_current_date to get today's date + 3. Use calculate_days_between to compute days since the event + 4. Return dates in ISO format (YYYY-MM-DD) + 5. Be precise with dates and descriptions """ ... async def main(): - # Example 1: Recent tech launch event - print("\nExample 1: Latest iPhone Launch") + # Example: Query about the moon landing + print("\nExample: First Moon Landing") print("-" * 50) - result = await analyze_event(EventInput(query="When was the latest iPhone launched?")) + result = await analyze_historical_event( + HistoricalEventInput(query="When was the first moon landing?"), + ) print(result.output) + print("-" * 50) print(f"Cost: ${result.cost_usd}") print(f"Latency: {result.duration_seconds:.2f}s") - # Example 2: Recent space exploration event - print("\nExample 2: SpaceX Starship Launch") + # Example: Query about World War II + print("\nExample: End of World War II") print("-" * 50) - result = await analyze_event(EventInput(query="When was the latest SpaceX Starship test flight?")) + result = await analyze_historical_event( + HistoricalEventInput(query="When did World War II end?"), + ) print(result.output) + print("-" * 50) print(f"Cost: ${result.cost_usd}") print(f"Latency: {result.duration_seconds:.2f}s") From 52d19259d79c32ecde7a17703ca4754dcf85ee93 Mon Sep 17 00:00:00 2001 From: Pierre Date: Fri, 21 Feb 2025 15:34:21 -0700 Subject: [PATCH 3/4] refactor(examples): update agent function signatures - Change return type from Run[Output] to Output directly - Add .run() method calls to execute agent functions - Clean up imports ordering --- examples/02_agent_with_tools.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/02_agent_with_tools.py b/examples/02_agent_with_tools.py index 08aea50..80fc52d 100644 --- a/examples/02_agent_with_tools.py +++ b/examples/02_agent_with_tools.py @@ -9,12 +9,12 @@ import asyncio from datetime import date, datetime +from zoneinfo import ZoneInfo from pydantic import BaseModel, Field -from zoneinfo import ZoneInfo import workflowai -from workflowai import Model, Run +from workflowai import Model def get_current_date() -> str: @@ -65,7 +65,7 @@ class HistoricalEventOutput(BaseModel): model=Model.GEMINI_1_5_FLASH_LATEST, tools=[get_current_date, calculate_days_between], ) -async def analyze_historical_event(event_input: HistoricalEventInput) -> Run[HistoricalEventOutput]: +async def analyze_historical_event(event_input: HistoricalEventInput) -> HistoricalEventOutput: """ Find information about historical events and calculate days since they occurred. @@ -88,7 +88,7 @@ async def main(): # Example: Query about the moon landing print("\nExample: First Moon Landing") print("-" * 50) - result = await analyze_historical_event( + result = await analyze_historical_event.run( HistoricalEventInput(query="When was the first moon landing?"), ) print(result.output) @@ -99,7 +99,7 @@ async def main(): # Example: Query about World War II print("\nExample: End of World War II") print("-" * 50) - result = await analyze_historical_event( + result = await analyze_historical_event.run( HistoricalEventInput(query="When did World War II end?"), ) print(result.output) From 096cdf818d25666f626cb363106a151990824780 Mon Sep 17 00:00:00 2001 From: Pierre Date: Tue, 25 Feb 2025 10:29:44 -0700 Subject: [PATCH 4/4] Simplify agent example output to directly print run object instead of accessing individual properties --- examples/02_agent_with_tools.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/examples/02_agent_with_tools.py b/examples/02_agent_with_tools.py index 80fc52d..85289e5 100644 --- a/examples/02_agent_with_tools.py +++ b/examples/02_agent_with_tools.py @@ -88,24 +88,18 @@ async def main(): # Example: Query about the moon landing print("\nExample: First Moon Landing") print("-" * 50) - result = await analyze_historical_event.run( + run = await analyze_historical_event.run( HistoricalEventInput(query="When was the first moon landing?"), ) - print(result.output) - print("-" * 50) - print(f"Cost: ${result.cost_usd}") - print(f"Latency: {result.duration_seconds:.2f}s") + print(run) # Example: Query about World War II print("\nExample: End of World War II") print("-" * 50) - result = await analyze_historical_event.run( + run = await analyze_historical_event.run( HistoricalEventInput(query="When did World War II end?"), ) - print(result.output) - print("-" * 50) - print(f"Cost: ${result.cost_usd}") - print(f"Latency: {result.duration_seconds:.2f}s") + print(run) if __name__ == "__main__":