ChatGPT Now Sees Beyond 2021 with Function Calling!

ChatGPT Now Sees Beyond 2021 with Function Calling!
ChatGPT Function Calling - Generated by Bing Image Creator

In the world of artificial intelligence, OpenAI's ChatGPT has been making quite a splash. This language model has been turning heads with its ability to generate human-like text based on the prompts it's given.

But as we've been playing around with ChatGPT, we couldn't help but wish for one thing: more recent training data. As of its last update, ChatGPT was trained on data up until September 2021. While that's still impressive, we live in a fast-paced world where a lot can happen in a few months. Wouldn't it be great if ChatGPT could keep up with the times and provide insights based on the most recent data?

Well, our wishes have been granted. OpenAI has introduced a new feature that allows ChatGPT to call functions, opening up a whole new world of possibilities. This means that ChatGPT can now interact with external APIs, fetch the most recent data, and use it to generate responses.

In this article, we're going to dive into this exciting new feature, explore its benefits, brainstorm some cool applications, and walk through a real-world example. Let's get started!

What is OpenAI function calling?

Function calling is a feature introduced by OpenAI in their Chat Completions API. It allows developers to describe functions to the AI model, and the model can then decide to output a JSON object containing arguments to call those functions.

So, why is this a big deal? Well, function calling allows developers to connect GPT's capabilities with external tools and APIs in a more reliable way. It's like giving your AI assistant the ability to interact with the world outside its own mind. This opens up a whole new world of possibilities for developers to create more interactive and dynamic applications.

Five Ideas for Function Calling

I asked ChatGPT to come up with five ideas of things we could build with this feature that we couldn't do before:

  1. Chatbots that answer questions by calling external tools: Imagine a chatbot that can fetch real-time weather data, stock market trends, or even the latest news articles based on user queries.
  2. Natural language interface for APIs or databases: You could build an application that converts natural language queries into API calls or database queries. For example, a query like "Who are my top ten customers this month?" could be converted into an API call or a SQL query.
  3. Data extraction from text: You could define a function that extracts structured data from a text. For example, extracting all people mentioned in a Wikipedia article along with some information about them.
  4. Automated task execution: You could create a system where tasks are described in natural language and the AI assistant executes them by  calling the appropriate functions. For example, a task like "Email John the sales report for this month" could be converted into a function call to send an email.
  5. Interactive learning applications: You could build an application where users learn by interacting with the AI, and the AI calls functions to check their answers, provide hints, or even generate new problems for them to solve.

Now, let's dive into a real-world example to see this feature in action. To illustrate the potential of function calling, I've built a prototype based on the first idea from our brainstorming session. We'll create a simple application that fetches stock data and uses the AI to analyze the trend.

Our application is a Python script that accepts a stock ticker symbol as a command-line argument. It fetches the stock's price, 5-day Simple Moving Average (SMA), and 200-day SMA from the Alpha Vantage API, and then asks the AI to analyze the trend based on this data.

You can find the complete code here:

GitHub - ThinkMachina/ChatGPT-Functions-Calling: Experimenting with ChatGPT Functions
Experimenting with ChatGPT Functions. Contribute to ThinkMachina/ChatGPT-Functions-Calling development by creating an account on GitHub.

Please note, this is a proof of concept (PoC) that I built because I couldn’t find any comprehensive implementation from OpenAI. I'm aware that there's room for improvement, so bear with me!

The Code

Dependencies

# main.py
import os
import openai
import argparse
import requests
import json
import pandas as pd
...

We start by importing the necessary modules. os and argparse are used to handle environment variables and command-line arguments, requests is used to make HTTP requests to the Alpha Vantage API, json is used to handle JSON data, pandas is used to manipulate the stock data, and openai is the OpenAI Python client.

Fetch Stock Data


def get_stock_data(ticker: str):
    api_key = os.getenv("ALPHA_VANTAGE_API_KEY")
    base_url = "<https://www.alphavantage.co/query>"

    # Fetch daily adjusted close prices
    function = "TIME_SERIES_DAILY_ADJUSTED"
    query = f"{base_url}?function={function}&symbol={ticker}&outputsize=full&apikey={api_key}"
    response = requests.get(query)
    data = response.json()

    # Check if Alpha Vantage returned an error
    if "Error Message" in data:
        print(f"Error fetching data from Alpha Vantage: {data['Error Message']}")
        exit(-1)

    # Convert the data to a pandas DataFrame
    df = pd.DataFrame.from_dict(data["Time Series (Daily)"], orient="index")

    # Convert the '5. adjusted close' column to float
    df['5. adjusted close'] = df['5. adjusted close'].astype(float)

    # Get the closing price for today
    price = df["5. adjusted close"].iloc[0]

    # Calculate the 50-day and 200-day SMAs
    SMA_5 = df["5. adjusted close"].rolling(window=5).mean().iloc[4]
    SMA_200 = df["5. adjusted close"].rolling(window=200).mean().iloc[200]

    return price, SMA_5, SMA_200

Next, we define a function to fetch the stock data from Alpha Vantage. This function takes a stock ticker symbol as an argument, makes a request to the Alpha Vantage API, and returns the stock's price, 5-day SMA, and 200-day SMA.

Interacting with OpenAI API: Where the magic happens

This function, get_completion, is our bridge to the OpenAI API. It accepts a list of messages, which represent our conversation history with the AI.

The real star of the show is the functions parameter. This is where we describe our get_stock_data function to the AI. We tell it the function's name, what it does, and what parameters it needs.

By doing this, we're essentially teaching the AI about our function. We're saying, "Hey, if you need to fetch stock data, here's a function you can call. You just need to provide a stock ticker."


def get_completion(messages):
	response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=[
            {
                "name": "get_stock_data",
                "description": "Get the price, 5-day SMA, and 200-day SMA of a stock",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "ticker": {
                            "type": "string",
                            "description": "The stock ticker"
                        },
                    },
                    "required": ["ticker"],
                },
            },
        ]
    )

    return response

Main function

The main function is where the interaction with the AI truly comes to life. It's the heart of our script, orchestrating the flow of the conversation and managing the function calls.

We start by parsing the command-line arguments to get the stock ticker symbol. We then initialize the conversation with the AI by asking it about the trend of the specified stock.

We then enter a loop where we continuously interact with the AI. If the AI decides to stop, we print its final message and break the loop.

However, if the AI decides to call a function (in this case, get_stock_data), this is where things get interesting. The arguments needed to call the function are actually provided by the AI itself in the completion response. We simply extract these arguments and call the function with them.

This is a key aspect of OpenAI's function calling feature. The AI not only knows about our function, but it also knows when to call it and what arguments to provide. This allows for a dynamic and interactive conversation where the AI can fetch real-time data as needed.

After calling the function, we add the function call and its result to the conversation history. This allows the AI to reference the function call and its result in its subsequent responses. We then continue the interaction with the AI, fetching new data and generating new insights as the conversation progresses.

This loop continues until the AI decides to stop, providing a dynamic and interactive conversation that leverages real-time data to generate insights.

def main():
    # Parse command-line arguments
    parser = argparse.ArgumentParser(description='Fetch stock data and analyze trend.')
    parser.add_argument('ticker', help='The stock ticker symbol')
    args = parser.parse_args()
    
    openai.api_key = os.getenv("OPENAI_API_KEY")

    ticker = args.ticker
    messages = [
        {"role": "user", "content": f"What's the trend of {ticker} stock?"},
    ]

    while True:
        response = get_completion(messages)

        if response.choices[0]["finish_reason"] == "stop":
            print(response.choices[0]["message"]["content"])
            break

        elif response.choices[0]["finish_reason"] == "function_call":
            fn_name = response.choices[0].message["function_call"].name
            arguments = response.choices[0].message["function_call"].arguments
            args = json.loads(response['choices'][0]['message']['function_call']['arguments'])

            function = globals()[fn_name]
            price, SMA_5, SMA_200 = function(**args)

            messages.append(
                {
                    "role": "assistant",
                    "content": None,
                    "function_call": {
                        "name": fn_name,
                        "arguments": arguments,
                    },
                }
            )

            messages.append(
                {
                    "role": "function", 
                    "name": fn_name, 
                    "content": f'{{"price": {price}, "SMA_5": {SMA_5}, "SMA_200": {SMA_200}}}'}
            )

            response = get_completion(messages)

Seeing the script in action

Now, let's see our script in action. We'll run it with the ticker symbol for the Vanguard Total Stock Market ETF (VTI):


$ python main.py VTI

The AI responds with an analysis of the stock's trend:


The trend of VTI stock is currently showing a slight downward
movement. The current price is $218.18, which is slightly
lower than the 5-day Simple Moving Average (SMA) of $218.48.
However, it is still higher than the 200-day SMA of $197.93,
indicating a long-term upward trend.

Just like that, we've built a powerful application PoC that combines the capabilities of OpenAI's ChatGPT with real-time stock data. It fetches the latest data, analyzes it, and provides insights, all in a conversational manner.

But remember, this is just the beginning. The function calling feature opens up a world of possibilities. You can connect ChatGPT with various APIs, databases, or even your custom functions. The sky's the limit!

So, what are you waiting for? Dive in, explore, and create something amazing with OpenAI's function calling feature. And while you're at it, don't forget to join our community to stay ahead of the curve and keep up with the latest in AI and technology. Let's navigate the future together!