(test) parallel tool calling

This commit is contained in:
ishaan-jaff 2023-11-17 17:03:24 -08:00
parent fdbaceab8e
commit d2bac07b48

View file

@ -12,14 +12,12 @@ import pytest
import litellm import litellm
from litellm import embedding, completion, completion_cost, Timeout from litellm import embedding, completion, completion_cost, Timeout
from litellm import RateLimitError from litellm import RateLimitError
import pytest
litellm.num_retries = 3 litellm.num_retries = 3
litellm.cache = None litellm.cache = None
litellm.set_verbose=True litellm.set_verbose=False
import json import json
# Example dummy function hard coded to return the same weather
# In production, this could be your backend API or an external API
def get_current_weather(location, unit="fahrenheit"): def get_current_weather(location, unit="fahrenheit"):
"""Get the current weather in a given location""" """Get the current weather in a given location"""
if "tokyo" in location.lower(): if "tokyo" in location.lower():
@ -31,67 +29,79 @@ def get_current_weather(location, unit="fahrenheit"):
else: else:
return json.dumps({"location": location, "temperature": "unknown"}) return json.dumps({"location": location, "temperature": "unknown"})
def run_conversation(): # Example dummy function hard coded to return the same weather
# Step 1: send the conversation and available functions to the model # In production, this could be your backend API or an external API
messages = [{"role": "user", "content": "What's the weather like in San Francisco, Tokyo, and Paris?"}] def test_parallel_function_call():
tools = [ try:
{ # Step 1: send the conversation and available functions to the model
"type": "function", messages = [{"role": "user", "content": "What's the weather like in San Francisco, Tokyo, and Paris?"}]
"function": { tools = [
"name": "get_current_weather", {
"description": "Get the current weather in a given location", "type": "function",
"parameters": { "function": {
"type": "object", "name": "get_current_weather",
"properties": { "description": "Get the current weather in a given location",
"location": { "parameters": {
"type": "string", "type": "object",
"description": "The city and state, e.g. San Francisco, CA", "properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
}, },
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}, "required": ["location"],
}, },
"required": ["location"],
}, },
}, }
} ]
] response = litellm.completion(
response = litellm.completion(
model="gpt-3.5-turbo-1106",
messages=messages,
tools=tools,
tool_choice="auto", # auto is default, but we'll be explicit
)
print("Response\n", response)
response_message = response.choices[0].message
tool_calls = response_message.tool_calls
# Step 2: check if the model wanted to call a function
if tool_calls:
# Step 3: call the function
# Note: the JSON response may not always be valid; be sure to handle errors
available_functions = {
"get_current_weather": get_current_weather,
} # only one function in this example, but you can have multiple
messages.append(response_message) # extend conversation with assistant's reply
print("Response message\n", response_message)
# Step 4: send the info for each function call and function response to the model
for tool_call in tool_calls:
function_name = tool_call.function.name
function_to_call = available_functions[function_name]
function_args = json.loads(tool_call.function.arguments)
function_response = function_to_call(
location=function_args.get("location"),
unit=function_args.get("unit"),
)
messages.append(
{
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": function_response,
}
) # extend conversation with function response
second_response = litellm.completion(
model="gpt-3.5-turbo-1106", model="gpt-3.5-turbo-1106",
messages=messages, messages=messages,
) # get a new response from the model where it can see the function response tools=tools,
return second_response tool_choice="auto", # auto is default, but we'll be explicit
print(run_conversation()) )
print("Response\n", response)
response_message = response.choices[0].message
tool_calls = response_message.tool_calls
print("length of tool calls", len(tool_calls))
print("Expecting there to be 3 tool calls")
assert len(tool_calls) > 1 # this has to call the function for SF, Tokyo and parise
# Step 2: check if the model wanted to call a function
if tool_calls:
# Step 3: call the function
# Note: the JSON response may not always be valid; be sure to handle errors
available_functions = {
"get_current_weather": get_current_weather,
} # only one function in this example, but you can have multiple
messages.append(response_message) # extend conversation with assistant's reply
print("Response message\n", response_message)
# Step 4: send the info for each function call and function response to the model
for tool_call in tool_calls:
function_name = tool_call.function.name
function_to_call = available_functions[function_name]
function_args = json.loads(tool_call.function.arguments)
function_response = function_to_call(
location=function_args.get("location"),
unit=function_args.get("unit"),
)
messages.append(
{
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": function_response,
}
) # extend conversation with function response
second_response = litellm.completion(
model="gpt-3.5-turbo-1106",
messages=messages,
) # get a new response from the model where it can see the function response
print("second response\n", second_response)
return second_response
except Exception as e:
pytest.fail(f"Error occurred: {e}")
test_parallel_function_call()