In real-world applications, the need for precise function invocation becomes especially crucial within the context
of multi-turn conversations. These scenarios demand not only the accurate identification and execution of functions
based on user inputs but also the preservation of context across multiple interactions.
Typical use cases, for example, include scenarios such as engaging with a support agent or implementing workflow automation.
These applications benefit significantly from a system’s ability to understand and respond to a sequence of user inputs coherently,
ensuring a smooth and effective user experience.
How to Use
Multi-turn tool calling is similar to single-turn tool calling, as illustrated in this example, but it can involve multiple rounds.
It utilizes the results of previous conversations—including the assistant’s messages, user messages, or tool calls and their
responses—to infer the next response.
Code Example
In this example, we create a highly simplified customer support bot to demonstrate a basic multi-turn tool calling scenario.
Specifically, we instruct the bot to first verify the user’s identity and then check the ticket status for the user.
The model is required to automatically decide whether to call functions or send messages.
Additionally, it must understand the flow and current status from the conversation context.
from openai import OpenAI
import json
client = OpenAI(
base_url="https://app.empower.dev/api/v1",
api_key="YOUR_API_KEY"
)
def get_ticket_status(ticket_id: str):
"""Returns mock ticket status based on the ticket ID."""
status_data = {
"12345": {"status": "Open", "issue": "Billing Query"},
"67890": {"status": "Closed", "issue": "Technical Support"},
}
return status_data.get(ticket_id, {"status": "Unknown", "issue": "Unknown"})
def verify_user(username: str, api_key: str):
"""Verify user based on username and API key."""
return {
"success": True,
}
tools = [
{
"type": "function",
"function": {
"name": "get_ticket_status",
"description": "Returns mock ticket status based on the ticket ID.",
"parameters": {
"type": "object",
"properties": {
"ticket_id": {
"type": "string",
"description": "The unique identifier for the ticket."
}
},
"required": ["ticket_id"]
}
}
},
{
"type": "function",
"function": {
"name": "verify_user",
"description": "Verifies the user based on the provided username and API key.",
"parameters": {
"type": "object",
"properties": {
"username": {
"type": "string",
"description": "The username of the user to be verified."
},
"api_key": {
"type": "string",
"description": "The API key provided by the user for verification."
}
},
"required": ["username", "api_key"]
}
}
}
]
def call_model(messages):
""" Call the model used the provided messages """
system_message = {
"role": "system",
"content": """
You are a customer support agent you job is to help users check ticket status.
Make sure you verify the user before checking the ticket status.
Start by greeting the user.
"""
}
return client.chat.completions.create(
model="empower-functions",
messages=[system_message] + messages,
tools=tools,
temperature=0
)
def call_function_and_get_response(function_name, function_arguments):
""" Run the "function_name" using "function_argument" and convert the response into a "tool" message
function_response = globals()[function_name](**function_arguments)
return {
"role": "tool",
"tool_call_id": tool.id,
"content": json.dumps(function_response)
}
user_messages = [
{
'role': 'user',
'content': 'Hi there, my username is john_doe, can you help me check the status for my ticket?'
},
{
'role': 'user',
'content': 'Sure, my username is "john_doe" and my API key is: "key"'
},
{
'role': 'user',
'content': 'Yea it\'s: 12345'
},
{
'role': 'user',
'content': 'That\'s it, thanks.'
}
]
messages = []
while True:
response = call_model(messages)
messages.append(response.choices[0].message)
if response.choices[0].message.content:
print(f"assistant: {response.choices[0].message.content}")
if not user_messages:
break
user_message = user_messages.pop(0)
print(f"user: {user_message['content']}")
messages.append(user_message)
else:
response_message = response.choices[0].message
tool = response_message.tool_calls[0]
function = tool.function
function_name = function.name
function_arguments = json.loads(function.arguments)
print(
f"assistant: call function {function_name}, with arguments {function_arguments}")
tool_message = call_function_and_get_response(
function_name, function_arguments)
print(f"function response: {tool_message['content']}")
messages.append(tool_message)
Output: