diff --git a/contributing/samples/tools/parallel_functions/agent.py b/contributing/samples/tools/parallel_functions/agent.py index d745fdc6..02327509 100644 --- a/contributing/samples/tools/parallel_functions/agent.py +++ b/contributing/samples/tools/parallel_functions/agent.py @@ -60,7 +60,7 @@ async def get_weather(city: str, tool_context: ToolContext) -> dict: if 'weather_requests' not in tool_context.state: tool_context.state['weather_requests'] = [] tool_context.state['weather_requests'].append( - {'city': city, 'timestamp': time.time(), 'result': result} + {'city': city, 'result': result} ) return { @@ -108,14 +108,12 @@ async def get_currency_rate( 'from': from_currency, 'to': to_currency, 'rate': rate, - 'timestamp': time.time(), }) return { 'from_currency': from_currency, 'to_currency': to_currency, 'exchange_rate': rate, - 'timestamp': time.time(), } @@ -163,7 +161,6 @@ async def calculate_distance( 'city1': city1, 'city2': city2, 'distance': distance, - 'timestamp': time.time(), }) return { @@ -204,7 +201,7 @@ async def get_population(cities: List[str], tool_context: ToolContext) -> dict: if 'population_requests' not in tool_context.state: tool_context.state['population_requests'] = [] tool_context.state['population_requests'].append( - {'cities': cities, 'results': results, 'timestamp': time.time()} + {'cities': cities, 'results': results} ) return { diff --git a/contributing/samples/tools/parallel_functions/tests/test_all_tools.json b/contributing/samples/tools/parallel_functions/tests/test_all_tools.json new file mode 100644 index 00000000..3d5c7875 --- /dev/null +++ b/contributing/samples/tools/parallel_functions/tests/test_all_tools.json @@ -0,0 +1,196 @@ +{ + "events": [ + { + "author": "user", + "content": { + "parts": [ + { + "text": "Tell me about Paris and Sydney: weather, distance between them, and their populations." + } + ], + "role": "user" + }, + "id": "e-1", + "invocationId": "i-1", + "nodeInfo": { + "path": "" + } + }, + { + "author": "parallel_function_test_agent", + "content": { + "parts": [ + { + "functionCall": { + "args": { + "city": "Paris" + }, + "id": "fc-1", + "name": "get_weather" + } + }, + { + "functionCall": { + "args": { + "city": "Sydney" + }, + "id": "fc-2", + "name": "get_weather" + } + }, + { + "functionCall": { + "args": { + "city1": "Paris", + "city2": "Sydney" + }, + "id": "fc-3", + "name": "calculate_distance" + } + }, + { + "functionCall": { + "args": { + "cities": [ + "Paris", + "Sydney" + ] + }, + "id": "fc-4", + "name": "get_population" + } + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-2", + "invocationId": "i-1", + "longRunningToolIds": [], + "nodeInfo": { + "path": "parallel_function_test_agent@1" + } + }, + { + "actions": { + "stateDelta": { + "distance_requests": [ + { + "city1": "Paris", + "city2": "Sydney", + "distance": 18903 + } + ], + "population_requests": [ + { + "cities": [ + "Paris", + "Sydney" + ], + "results": { + "Paris": 2161000, + "Sydney": 5312163 + } + } + ], + "weather_requests": [ + { + "city": "Paris", + "result": { + "condition": "overcast", + "humidity": 70, + "temp": 58 + } + }, + { + "city": "Sydney", + "result": { + "condition": "sunny", + "humidity": 60, + "temp": 75 + } + } + ] + } + }, + "author": "parallel_function_test_agent", + "content": { + "parts": [ + { + "functionResponse": { + "id": "fc-1", + "name": "get_weather", + "response": { + "city": "Paris", + "condition": "overcast", + "humidity": 70, + "temperature": 58 + } + } + }, + { + "functionResponse": { + "id": "fc-2", + "name": "get_weather", + "response": { + "city": "Sydney", + "condition": "sunny", + "humidity": 60, + "temperature": 75 + } + } + }, + { + "functionResponse": { + "id": "fc-3", + "name": "calculate_distance", + "response": { + "city1": "Paris", + "city2": "Sydney", + "distance_km": 18903, + "distance_miles": 11745 + } + } + }, + { + "functionResponse": { + "id": "fc-4", + "name": "get_population", + "response": { + "cities_count": 2, + "populations": { + "Paris": 2161000, + "Sydney": 5312163 + }, + "total_population": 7473163 + } + } + } + ], + "role": "user" + }, + "id": "e-3", + "invocationId": "i-1", + "nodeInfo": { + "path": "parallel_function_test_agent@1" + } + }, + { + "author": "parallel_function_test_agent", + "content": { + "parts": [ + { + "text": "Here's the information about Paris and Sydney:\n\n**Paris:**\n* **Weather:** The current weather in Paris is overcast with a temperature of 58\u00b0F and 70% humidity.\n* **Population:** The population of Paris is 2,161,000.\n\n**Sydney:**\n* **Weather:** The current weather in Sydney is sunny with a temperature of 75\u00b0F and 60% humidity.\n* **Population:** The population of Sydney is 5,312,163.\n\n**Distance between Paris and Sydney:**\nThe distance between Paris and Sydney is 18,903 km (11,745 miles)." + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-4", + "invocationId": "i-1", + "nodeInfo": { + "path": "parallel_function_test_agent@1" + } + } + ] +} \ No newline at end of file diff --git a/contributing/samples/tools/parallel_functions/tests/test_parallel_mixed.json b/contributing/samples/tools/parallel_functions/tests/test_parallel_mixed.json new file mode 100644 index 00000000..e4bb7191 --- /dev/null +++ b/contributing/samples/tools/parallel_functions/tests/test_parallel_mixed.json @@ -0,0 +1,128 @@ +{ + "events": [ + { + "author": "user", + "content": { + "parts": [ + { + "text": "What is the weather in Tokyo and the exchange rate from USD to EUR?" + } + ], + "role": "user" + }, + "id": "e-1", + "invocationId": "i-1", + "nodeInfo": { + "path": "" + } + }, + { + "author": "parallel_function_test_agent", + "content": { + "parts": [ + { + "functionCall": { + "args": { + "city": "Tokyo" + }, + "id": "fc-1", + "name": "get_weather" + } + }, + { + "functionCall": { + "args": { + "from_currency": "USD", + "to_currency": "EUR" + }, + "id": "fc-2", + "name": "get_currency_rate" + } + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-2", + "invocationId": "i-1", + "longRunningToolIds": [], + "nodeInfo": { + "path": "parallel_function_test_agent@1" + } + }, + { + "actions": { + "stateDelta": { + "currency_requests": [ + { + "from": "USD", + "rate": 0.85, + "to": "EUR" + } + ], + "weather_requests": [ + { + "city": "Tokyo", + "result": { + "condition": "rainy", + "humidity": 90, + "temp": 68 + } + } + ] + } + }, + "author": "parallel_function_test_agent", + "content": { + "parts": [ + { + "functionResponse": { + "id": "fc-1", + "name": "get_weather", + "response": { + "city": "Tokyo", + "condition": "rainy", + "humidity": 90, + "temperature": 68 + } + } + }, + { + "functionResponse": { + "id": "fc-2", + "name": "get_currency_rate", + "response": { + "exchange_rate": 0.85, + "from_currency": "USD", + "to_currency": "EUR" + } + } + } + ], + "role": "user" + }, + "id": "e-3", + "invocationId": "i-1", + "nodeInfo": { + "path": "parallel_function_test_agent@1" + } + }, + { + "author": "parallel_function_test_agent", + "content": { + "parts": [ + { + "text": "The weather in Tokyo is rainy with a temperature of 68 degrees Fahrenheit and 90% humidity. The exchange rate from USD to EUR is 0.85." + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-4", + "invocationId": "i-1", + "nodeInfo": { + "path": "parallel_function_test_agent@1" + } + } + ] +} \ No newline at end of file diff --git a/contributing/samples/tools/parallel_functions/tests/test_parallel_weather.json b/contributing/samples/tools/parallel_functions/tests/test_parallel_weather.json new file mode 100644 index 00000000..7c8e4b7d --- /dev/null +++ b/contributing/samples/tools/parallel_functions/tests/test_parallel_weather.json @@ -0,0 +1,129 @@ +{ + "events": [ + { + "author": "user", + "content": { + "parts": [ + { + "text": "What is the weather in New York and London?" + } + ], + "role": "user" + }, + "id": "e-1", + "invocationId": "i-1", + "nodeInfo": { + "path": "" + } + }, + { + "author": "parallel_function_test_agent", + "content": { + "parts": [ + { + "functionCall": { + "args": { + "city": "New York" + }, + "id": "fc-1", + "name": "get_weather" + } + }, + { + "functionCall": { + "args": { + "city": "London" + }, + "id": "fc-2", + "name": "get_weather" + } + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-2", + "invocationId": "i-1", + "longRunningToolIds": [], + "nodeInfo": { + "path": "parallel_function_test_agent@1" + } + }, + { + "actions": { + "stateDelta": { + "weather_requests": [ + { + "city": "New York", + "result": { + "condition": "sunny", + "humidity": 45, + "temp": 72 + } + }, + { + "city": "London", + "result": { + "condition": "cloudy", + "humidity": 80, + "temp": 60 + } + } + ] + } + }, + "author": "parallel_function_test_agent", + "content": { + "parts": [ + { + "functionResponse": { + "id": "fc-1", + "name": "get_weather", + "response": { + "city": "New York", + "condition": "sunny", + "humidity": 45, + "temperature": 72 + } + } + }, + { + "functionResponse": { + "id": "fc-2", + "name": "get_weather", + "response": { + "city": "London", + "condition": "cloudy", + "humidity": 80, + "temperature": 60 + } + } + } + ], + "role": "user" + }, + "id": "e-3", + "invocationId": "i-1", + "nodeInfo": { + "path": "parallel_function_test_agent@1" + } + }, + { + "author": "parallel_function_test_agent", + "content": { + "parts": [ + { + "text": "The weather in New York is sunny with a temperature of 72 degrees Fahrenheit and 45% humidity. In London, it is cloudy with a temperature of 60 degrees Fahrenheit and 80% humidity." + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-4", + "invocationId": "i-1", + "nodeInfo": { + "path": "parallel_function_test_agent@1" + } + } + ] +} \ No newline at end of file diff --git a/contributing/samples/tools/pydantic_argument/tests/test_create_company.json b/contributing/samples/tools/pydantic_argument/tests/test_create_company.json new file mode 100644 index 00000000..0d6909f9 --- /dev/null +++ b/contributing/samples/tools/pydantic_argument/tests/test_create_company.json @@ -0,0 +1,139 @@ +{ + "events": [ + { + "author": "user", + "content": { + "parts": [ + { + "text": "Create a profile for company Acme Corp in tech industry with 50 employees." + } + ], + "role": "user" + }, + "id": "e-1", + "invocationId": "i-1", + "nodeInfo": { + "path": "" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "functionCall": { + "args": { + "entity": { + "company_name": "Acme Corp", + "employee_count": 50, + "industry": "tech" + } + }, + "id": "fc-1", + "name": "create_entity_profile" + } + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-2", + "invocationId": "i-1", + "longRunningToolIds": [], + "nodeInfo": { + "path": "profile_agent@1" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "functionResponse": { + "id": "fc-1", + "name": "create_entity_profile", + "response": { + "message": "Unexpected entity type: ", + "status": "error" + } + } + } + ], + "role": "user" + }, + "id": "e-3", + "invocationId": "i-1", + "nodeInfo": { + "path": "profile_agent@1" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "functionCall": { + "args": { + "entity": { + "company_name": "Acme Corp", + "employee_count": 50, + "industry": "tech" + } + }, + "id": "fc-2", + "name": "create_entity_profile" + } + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-4", + "invocationId": "i-1", + "longRunningToolIds": [], + "nodeInfo": { + "path": "profile_agent@1" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "functionResponse": { + "id": "fc-2", + "name": "create_entity_profile", + "response": { + "message": "Unexpected entity type: ", + "status": "error" + } + } + } + ], + "role": "user" + }, + "id": "e-5", + "invocationId": "i-1", + "nodeInfo": { + "path": "profile_agent@1" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "text": "I apologize for the repeated errors. It seems I am having trouble with the tool's expected input format. I will try again to create the company profile for Acme Corp. I believe the issue was in how I was structuring the data for the `create_entity_profile` function. I will now use the correct dataclass constructor to create the profile. Please bear with me." + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-6", + "invocationId": "i-1", + "nodeInfo": { + "path": "profile_agent@1" + } + } + ] +} \ No newline at end of file diff --git a/contributing/samples/tools/pydantic_argument/tests/test_create_user.json b/contributing/samples/tools/pydantic_argument/tests/test_create_user.json new file mode 100644 index 00000000..37452017 --- /dev/null +++ b/contributing/samples/tools/pydantic_argument/tests/test_create_user.json @@ -0,0 +1,104 @@ +{ + "events": [ + { + "author": "user", + "content": { + "parts": [ + { + "text": "Create a user account for Alice, age 30, email alice@example.com." + } + ], + "role": "user" + }, + "id": "e-1", + "invocationId": "i-1", + "nodeInfo": { + "path": "" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "functionCall": { + "args": { + "profile": { + "age": 30, + "email": "alice@example.com", + "name": "Alice" + } + }, + "id": "fc-1", + "name": "create_full_user_account" + } + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-2", + "invocationId": "i-1", + "longRunningToolIds": [], + "nodeInfo": { + "path": "profile_agent@1" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "functionResponse": { + "id": "fc-1", + "name": "create_full_user_account", + "response": { + "conversion_demo": { + "preferences_converted": "JSON dict \u2192 UserPreferences instance", + "profile_converted": "JSON dict \u2192 UserProfile instance" + }, + "message": "Full account created for Alice!", + "preferences": { + "language": "English", + "notifications_enabled": true, + "preferences_type": "UserPreferences", + "theme": "light" + }, + "profile": { + "age": 30, + "email": "alice@example.com", + "name": "Alice", + "profile_type": "UserProfile" + }, + "status": "account_created" + } + } + } + ], + "role": "user" + }, + "id": "e-3", + "invocationId": "i-1", + "nodeInfo": { + "path": "profile_agent@1" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "text": "I have created a user account for Alice, age 30, with the email alice@example.com." + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-4", + "invocationId": "i-1", + "nodeInfo": { + "path": "profile_agent@1" + } + } + ] +} \ No newline at end of file diff --git a/contributing/samples/tools/pydantic_argument/tests/test_create_user_with_prefs.json b/contributing/samples/tools/pydantic_argument/tests/test_create_user_with_prefs.json new file mode 100644 index 00000000..37e52b5d --- /dev/null +++ b/contributing/samples/tools/pydantic_argument/tests/test_create_user_with_prefs.json @@ -0,0 +1,107 @@ +{ + "events": [ + { + "author": "user", + "content": { + "parts": [ + { + "text": "Create a user account for Bob, age 25, with dark theme and French language." + } + ], + "role": "user" + }, + "id": "e-1", + "invocationId": "i-1", + "nodeInfo": { + "path": "" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "functionCall": { + "args": { + "preferences": { + "language": "French", + "theme": "dark" + }, + "profile": { + "age": 25, + "name": "Bob" + } + }, + "id": "fc-1", + "name": "create_full_user_account" + } + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-2", + "invocationId": "i-1", + "longRunningToolIds": [], + "nodeInfo": { + "path": "profile_agent@1" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "functionResponse": { + "id": "fc-1", + "name": "create_full_user_account", + "response": { + "conversion_demo": { + "preferences_converted": "JSON dict \u2192 UserPreferences instance", + "profile_converted": "JSON dict \u2192 UserProfile instance" + }, + "message": "Full account created for Bob!", + "preferences": { + "language": "French", + "notifications_enabled": true, + "preferences_type": "UserPreferences", + "theme": "dark" + }, + "profile": { + "age": 25, + "email": "Not provided", + "name": "Bob", + "profile_type": "UserProfile" + }, + "status": "account_created" + } + } + } + ], + "role": "user" + }, + "id": "e-3", + "invocationId": "i-1", + "nodeInfo": { + "path": "profile_agent@1" + } + }, + { + "author": "profile_agent", + "content": { + "parts": [ + { + "text": "OK. I have created a user account for Bob, age 25, with a dark theme and French language preference." + } + ], + "role": "model" + }, + "finishReason": "STOP", + "id": "e-4", + "invocationId": "i-1", + "nodeInfo": { + "path": "profile_agent@1" + } + } + ] +} \ No newline at end of file