Introduction

We’ve already explored the functionality of function calling within OpenAI, where it identifies the requirement for a function call based on user prompts and responds with a JSON object containing arguments to call your functions. Upon requesting a function call, the model executes it and sends back the results to the API.

For further details on function calling in OpenAI, you can explore the following blog: OpenAI Function Calling with External API Examples

In a function calling, the model is able to identify only one function from the user query at a time. Due to that, it is not able to recognize multiple functions required from the user input in a single query, which is a limitation of using function calling without the parallel feature.

In the provided use case, if we aim to fetch stock prices for multiple symbols within a single user input or if we require extracting both stock prices and exchange rates in one user query, it poses a challenge without using parallel function calls. Presently, the system is limited to returning results for one query at a time.

Consider the following interaction without the parallel function calling feature:

Please enter your question here: (if you want to exit then write 'exit' or 'bye'.) What is stock price for apple and microsoft?
Response is:  173.5
Please enter your question here: What is stock price for aaple and Currency exchange rate between india and canada? 
Response is:  173.5
Please enter your question here: exit

As demonstrated, when multiple questions are asked in one user input without parallel function calling, the model only returns results for one query, showcasing the limitation.

To address the above issue, parallel function calling comes into play.

Parallel function calling involves the model’s ability to identify and execute multiple functions simultaneously, enabling the resolution of their results in parallel.

In this blog, we’ll explore how parallel function calling functionality enables us to extract multiple function responses for a single user query. 

We’ll focus on a use case demonstrated in the blog OpenAI Function Calling with External API Examples. This use case involves accessing an external API to obtain the current stock price of a company listed in the United States and the current currency exchange rate between two countries. It’s important to know these basics before diving into the tutorial.

Let’s dive into how the parallel function calling feature works.

Step 1:

To get started, install two packages, openai, and finnhub-python, with the following commands:

pip install openai
pip install finnhub-python

After installation, import the required libraries into your code:

import json
import requests
import finnhub
import openai
Step 2:

For this blog, we require the following API keys. Please generate your own keys as described in the previous blog and replace them with placeholders. Also, mention the model name that you want to experiment with:

GPT_MODEL = "gpt-3.5-turbo-0613"
finnhub_api_key = "your_finnhub_api_key"
openai_api_key = "your_openai_api_key"
alphavantage_api_key = "your_alphavantage_api_key"
Step 3:

Let’s define a function to get the current stock price of any US-listed company using the Finnhub API. First, you’ll need to set up your connection to the Finnhub API by providing your API key. Then, we’ll write a function to fetch the stock price.

finnhub_client = finnhub.Client(api_key = finnhub_api_key)
def get_current_stock_price(ticker_symbol):
   try:
       price_data=finnhub_client.quote(ticker_symbol)
       stock_price = price_data.get('c', None)
       if stock_price == 0:
           return "This company is not listed within USA, please provide another name."
       else:
           return str(stock_price)
   except:
       return "This company is not listed within USA, please provide another name."
Step 4:

Now, let’s make another function to get the currency exchange rate between two countries using the Alpha Vantage API. We’ll just add some code to our program to do this.

def currency_exchange_rate(from_country_currency,to_country_currency):
   try:
       # from_country_currency = json.loads(arguments)['from_country_currency']
       # to_country_currency = json.loads(arguments)['to_country_currency']
       url = f'https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency={from_country_currency}&to_currency={to_country_currency}&apikey={alphavantage_api_key}'
       r = requests.get(url)
       data = r.json()
       return data['Realtime Currency Exchange Rate']['5. Exchange Rate']
   except:
       return "I am unable to parse this, please try something new."
Step 5:

To enable parallel function calling, we need to define the function specification under the “tools” attribute. This allows multiple functions to be called simultaneously. In the specification, we provide the name and description of the function along with its parameters. Here’s how we can describe the specifications of the tools:

tools = [
       {
           "type": "function",
           "function": {
               "name": "get_current_stock_price",
               "description": "It will get the current stock price of the US company.",
               "parameters": {
                   "type": "object",
                   "properties": {
                       "ticker_symbol": {
                           "type": "string",
                           "description": "This is the symbol of the company.",
                       },
                   },
                   "required": ["ticker_symbol"],
               },
           },
       },
        {
           "type": "function",
           "function": {
               "name": "currency_exchange_rate",
               "description": "It will get the currency exchange rate between 2 countries.",
               "parameters": {
                   "type": "object",
                   "properties": {
                   "from_country_currency": {
                       "type": "string",
                       "description": "This is the currency of the country whose we need to map.",
                   },
                   "to_country_currency": {
                       "type": "string",
                       "description": "This is the currency of the country to which we need to map.",
                   }
               },
                   "required": ["from_country_currency","to_country_currency"],
               },
           },
       }

   ]
Step 6:

With OpenAI’s parallel function-calling feature, we can do some powerful stuff. We can use the below code to create JSON data which will be used further to call a local function. Then, It will call the local function and fetch details. After that, we take those details and hand them over to ChatGPT. It then works its magic and gives us a response that sounds just like a human wrote it!


user_input = input("Please enter your question here: (if you want to exit then write 'exit' or 'bye'.) ")

while user_input.strip().lower() != "exit" and user_input.strip().lower() != "bye":
   # prompt
   openai.api_key = openai_api_key
   client = openai
   messages = [{"role": "user", "content": user_input}]
   response = client.chat.completions.create(
       model= GPT_MODEL,
       messages=messages,
       tools=tools,
       tool_choice="auto",  # auto is default, but we'll be explicit
   )
   response_message = response.choices[0].message
   tool_calls = response_message.tool_calls

   if tool_calls:
         # Note: the JSON response may not always be valid; be sure to handle errors
         available_functions = {
             "get_current_stock_price": get_current_stock_price,
             "currency_exchange_rate":currency_exchange_rate,
         }  
         messages.append(response_message)  # extend conversation with assistant's reply
         
          #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
             if function_name == "get_current_stock_price":
                 function_to_call = available_functions["get_current_stock_price"]
                 function_args = json.loads(tool_call.function.arguments)
                 function_response = function_to_call(
                   ticker_symbol=function_args.get("ticker_symbol"),
                 )
             if function_name == "currency_exchange_rate":
                 function_to_call = available_functions["currency_exchange_rate"]
                 function_args = json.loads(tool_call.function.arguments)
                 function_response = function_to_call(
                   from_country_currency=function_args.get("from_country_currency"),
                   to_country_currency=function_args.get("to_country_currency"),

                 )
             messages.append(
                 {
                     "tool_call_id": tool_call.id,
                     "role": "tool",
                     "name": function_name,
                     "content": function_response,
                 }
             )  # extend conversation with function response
         second_response = client.chat.completions.create(
             model=GPT_MODEL,
             messages=messages,
         )  # get a new response from the model where it can see the function response
         result=second_response.choices[0].message.content
         print("Response:",result)

   user_input = input("Please enter your question here: ")
 Result:

In a previous blog, we utilized the model “gpt-3.5-turbo-0613”. Below is the conversation generated using the “gpt-3.5-turbo-0613” model.

Please enter your question here: (if you want to exit then write 'exit' or 'bye'.) What is stock price for apple and microsoft?
Response: The current stock price for Apple (AAPL) is $173.5.
I need the ticker symbol for Microsoft to fetch its stock price. Please provide it.
Please enter your question here: What is stock price for aaple and Currency exchange rate between india and canada?
Response: The current stock price for Apple (AAPL) is $173.50.

As for the currency exchange rate between India and Canada, it fluctuates regularly. It is best to check with a reliable financial institution or visit a reputable currency exchange website for the most accurate and up-to-date exchange rate.
Please enter your question here: exit

You can observe that it’s unable to respond to both queries; it only responds to the first one. Hence, we tried another latest model, “gpt-3.5-turbo-0125”, which can provide results for both queries. Below is the conversation generated using the “gpt-3.5-turbo-0125” model.

Please enter your question here: (if you want to exit then write 'exit' or 'bye'.) What is stock price for apple and microsoft?
Response: The current stock price for Apple (AAPL) is $173.50 and for Microsoft (MSFT) is $402.25.
Please enter your question here: What is stock price for aaple and Currency exchange rate between india and canada?
Response: The current stock price for Apple (AAPL) is $173.50. The currency exchange rate between India (INR) and Canada (CAD) is 1 INR to 0.0163 CAD.
Please enter your question here: exit

You can also use the below colab to run the above code.

https://colab.research.google.com/drive/1dc4XRkN_Lfyp109L5MbS23cHNkjLx8Xq#scrollTo=QojiotqDoVVO

Conclusion

In the blog post on parallel function calling, we’ve explored how this feature addresses the limitation of executing only one function per user query. By enabling the model to identify and execute multiple functions simultaneously, parallel function calling allows us to extract multiple function responses for a single user query efficiently. This enhances the capability to handle complex user queries that require data from multiple sources, streamlining workflows and providing more comprehensive responses.

Categories: ChatGPT Natural Language Processing NLP OpenAI

Leave a Reply

Your email address will not be published.

You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*