avatarYanli Liu

Summary

The provided content outlines a comprehensive guide to creating an AI financial analyst using OpenAI's Assistants API, which leverages advanced features like Code Interpretor, Retrieval, and customized function calling to analyze financial statements and forecast stock trends.

Abstract

The article details the development of an AI financial analyst capable of interpreting complex financial documents such as SEC Form 10-Q reports. It emphasizes the use of OpenAI's Assistants API, which integrates up to 128 custom tools and frameworks like AutoGen, to provide an agent-like experience in applications. The guide includes practical code examples, a step-by-step implementation process, and demonstrates how to use the API's three key capabilities: Retrieval, Code Interpretor, and Function Calling. The author provides a Colab notebook for hands-on exploration and discusses the cost implications of using GPT-4 and OpenAI-hosted tools. The article also covers the versatility of the Assistants API, its potential to simplify complex tasks, and its adaptability to various use cases beyond financial analysis.

Opinions

  • The author suggests that there is an inherent satisfaction in understanding the underlying mechanisms of coding and utilizing the Assistants API.
  • They imply that the Assistants API offers greater control and enhanced capabilities compared to no-code Custom GPT solutions.
  • The article conveys that integrating the Retrieval tool simplifies the process of incorporating external knowledge, eliminating the need for a complex RAG pipeline.
  • The author expresses that the Code Interpreter feature is powerful for dynamic data processing and visualization within applications.
  • It is suggested that the ability to define custom functions enhances the utility and flexibility of AI applications.
  • The author indicates that the Assistants API is versatile and suitable for a wide range of use cases, including data analysis and AI-powered vacation planning.
  • The article hints at the potential for higher costs associated with GPT-4 compared to GPT-3.5 and the additional fees for using OpenAI-hosted tools.
  • The author encourages readers to follow and subscribe to their Medium account for further support and updates on their work.

Mastering OpenAI Assistants API: Building an AI Financial Analyst to Forecast Stock Trend

A Complete Finance Use Case Implementation Leveraging Code Interpreter, Retrieval, and Customized Function Calling Capabilities

Financial statements, such as SEC Form 10-Q reports, are gold mines of crucial information about a company’s financial health. When these statements are released, stock prices often react, either positively or negatively, depending on the results and market expectations.

However, these documents are often lengthy and not easily comprehensible for individuals who aren’t finance experts.

In this post, I’ll guide you through on how to use OpenAI’s latest Assistants API to create an AI financial analyst. This AI will be capable of analyzing financial statements, extracting valuable insights, and saving you precious time.

AI Financial Analyst. Graph by author.

I’ll demonstrate how to achieve this with practical code examples, leveraging the three superpowers unleashed by GPT-4:

  1. Retrieval
  2. Code Interpretor
  3. Function Calling, enabling you to define your custom functions.

The Colab notebook will be shared at the end of the article so you can explore the Assitants API easily!

You might wonder why not use a no-code Custom GPT for this task? Well, the Assistants API offers greater control, enhanced capabilities, and the potential to develop applications that go far beyond chatbots. With this API, you can equip your AI applications with up to 128 customized tools and seamlessly integrate them with other frameworks like AutoGen.

And, let’s not forget, there’s something inherently satisfying about understanding what’s happening under the hood and diving into the world of coding, isn’t there?

Table of Contents:

  1. Understanding the Basics 1.1. What Is OpenAI Assitants API ? 1.2. How Assitstants API Work? 1.3. Why Use Assistants API?
  2. Implementing the AI Financial Analyst 2.1. Designing the Application 2.2. Step-by-step Guide to Coding with the Assistants API 2.3. Hands-on Exemples on Retrieval 2.4. Hands-on Exemples on Code Interpretor 2.5. Hands-on Exemples on Custom functions
  3. Closing thoughts

Understanding the Basics

What Is OpenAI Assitants API ?

The Assistants API is a game changer feature recently introduced after OpenAI Dev Day. It simplifies the creation of assistant-like experiences and is powered by built-in capabilities such as Code Interpretation and Retrieval. With this API, you can integrate up to 128 tools, with custom functions for performing specific tasks.

An Assistant operates similar to an agent, autonomously using models, tools, and knowledge to respond to user queries.

How Assitstants API Work?

We can summarize the creation of an Assistant in 5 steps :

The 5 steps of creating and interacting with an Assistant. Image by author.
  1. Create an Assistant in the API by defining its custom instructions and picking a model.
  2. Create a Thread when a user starts a conversation.
  3. Add Messages to the Thread as the user ask questions.
  4. Run the Assistant on the Thread to trigger responses. This automatically calls the relevant tools.
  5. Retrieve and display the Assistant’s Response

We have seen several important Assistants API objects. Let’s also quickly recap what these objects represent with the table below:

Assistants API objects .Source.

Why Use Assistants API?

  1. Agent-like Experiences in Apps: Seamlessly integrate advanced, interactive agent-like experiences into your apps. Whether it’s for analyzing data or planning vacations, this API brings a new level of interaction.
  2. Code Interpreter Feature: Execute and visualize Python code directly within your applications, offering dynamic data processing and visual representation capabilities.
  3. External Knowledge Integration: Incorporating external knowledges is extremly easy with the API! You do not need to build your RAG pipeline anymore with various steps such as chunking, turning the text chunks into embedding, storing them in a vectordatabase etc. You only need to tell the assistant that you want to use the Retrieval tool which will take care of all these tehcnical details.
  4. Customizable Functionality: Utilize function calling to tailor your assistants for specific tasks, enhancing their utility and flexibility in your applications. You can add up to 128 functions.
  5. Versatility in Use Cases: The API offers a wide range of use cases, including natural language-based data analysis apps, coding assistants, and AI-powered vacation planners.

Implementing the AI Financial Analyst

Designing the Application

In this demo, we will create an AI Financial Analyst with the following essential capabilities:

  1. Answering General Finance Questions
  2. Guiding Through Financial Statements
  3. Conducting In-Depth Data Analysis
  4. Emailing Summaries and Key Insights

Step-by-step Guide to Coding with the Assistants API

In this guide, we’ll focus on creating the Finance Assistant directly through the Assistants API. Alternatively, you can use Assitants Playground to help you create the assistant which is the the easiest way to get started.

Step 1 — Install Dependencies

Run the command below the install the lastest OpenAI package.

!pip install --upgrade openai

Set up your OpenAI API key. If you haven’t obtained an OpenAI API key yet, visit the OpenAI developer portal, sign up, and request an API key. Make sure to securely save the key.

OPENAI_KEY="sk-xxxx" #Your OpenAI API Key 

We’ll also create a helper function that formats and prints the Assistants API object in a readable JSON format.

import json

def show_json(obj):
    display(json.loads(obj.model_dump_json()))

Step 2 — Create the Finance Assitant

Creating an Assistant is a simple process. You need to specify:

  1. Name : Define your assistant name
  2. Model Name: Choose the model you want to use.
  3. Instructions: Define the instructions you want the Assistant to follow.
  4. Tools: Specify the tools you want the Assistant to utilize. In this case, we’ll use Retrieval and Code Interpreter Tool.
from openai import OpenAI
client = OpenAI(api_key=OPENAI_KEY)

assistant = client.beta.assistants.create(
    name = "Finance Insight Analyst",
    instructions = "You are a helpful  financial analyst expert and your are tailored for in-depth SEC 10-Q filings analysis, focusing on management discussions and financial results.",
    tools = [{"type":"code_interpreter"}, {"type": "retrieval"}],
    model = "gpt-4-1106-preview"
)

Once you’ve done this, your Assistant is created! Let’s have a look.

Assistant object. Image by author.

Whether you create your Assistant through the Dashboard or with the API, it’s important to keep track of the Assistant ID. This ID is how you’ll refer to your Assistant when working with Threads and Runs.

Step 3 — Create a Thread

We’ll create a Thread which will hold a conversation session beween an Assistant and a user. We do not need to send the entire history each time like in the preivous ChatCompletion API but to be noted you will still be charged for the tokens of the entire conversation history with each Run.

thread1 = client.beta.threads.create()

Step 4: Submit a Message to The Thread And Trigger The Run

We’ll consolidate the following steps:

  1. Add Messages to the Thread: As the user asks questions, we’ll add their messages to the Thread.
  2. Run the Assistant on the Thread: This action triggers responses from the Assistant and automatically calls the relevant tools.

It’s important to note that creating a Run is an asynchronous operation. Initially, it returns with the Run’s metadata, including a status that starts as “queued.” This status updates as the Assistant performs operations, such as using tools and adding messages. To determine when the Assistant has completed processing, we can continuously check the Run’s status in a loop.

Run objects can have multiple statuses. Source

To make this process more manageable, we’ll define the following functions that can be reused:

  • submit_message: This function submits a new user message to a thread and runs the Assistant on the thread.
  • wait_on_run: This function helps us track when the Assistant has finished processing so we can retrieve a response from the Assistant.
  • get_response: Once the Run is completed, we use this function to retrieve the response from the thread.
def submit_message(assistant_id, thread, user_message):
    client.beta.threads.messages.create(
        thread_id=thread.id, role="user", content=user_message
    )
    return client.beta.threads.runs.create(
        thread_id=thread.id,
        assistant_id=assistant_id,
    )


import time
# Waiting in a loop
def wait_on_run(run, thread):
    while run.status == "queued" or run.status == "in_progress":
        run = client.beta.threads.runs.retrieve(
            thread_id=thread.id,
            run_id=run.id,
        )
        time.sleep(0.5)
    return run

def get_response(thread):
    return client.beta.threads.messages.list(thread_id=thread.id, order="asc")

Step 5 — Get the Response

First, let’s define a helper function to print user messages and assistant messages in a more visually readable format.

# Pretty printing helper
def pretty_print(messages):
    print("# Messages")
    for m in messages:
        print(f"{m.role}: {m.content[0].text.value}")
    print()

Now, let’s try submitting a message, start the run, and get the responses after the run has finished.

run1 = submit_message(FINANCE_ASSISTANT_ID, thread1, "What is SEC Q-10 filing?")
run1 = wait_on_run(run1, thread1)
pretty_print(get_response(thread1))
Retrieve the response from the assistant. Image by author.

Hands-on Exemples on Retrieval

Now let’s upload a financial statement and ask the assitant to help us walkthrough it.

# Upload the file
file = client.files.create(
    file=open(
        "tsla-20231018-10Q.pdf",
        "rb",
    ),
    purpose="assistants",
)

Once the financial statement is uploaded, we’ll need to update the Assistant by providing it with the file ID. Files uploaded using the OpenAI Files API are stored and can be easily reused in the future by referencing their unique IDs.

# Update Assistant
assistant = client.beta.assistants.update(
    FINANCE_ASSISTANT_ID,
    file_ids=[file.id],
)
show_json(assistant)

We can now instruct the Assistant to provide a summary of the key takeaways from the financial statement. This saves us the time and effort of reading through the entire document.

thread = client.beta.threads.create()
run = submit_message(FINANCE_ASSISTANT_ID, thread, "Summarize the management discussion in this 10K filing and list key takeaways from this financial result")
run = wait_on_run(run, thread)
pretty_print(get_response(thread))

As you can see, implementing Retrieval Augmented Generation with the built-in Retrieval capability is quite straightforward. However, please be aware that using OpenAI-hosted tools may come with an additional fee.

Summary of Tesla’s financial statement. Image by author.

Hands-on Exemples on Code Interpreter

The Code Interpreter is a very powerful tool. It not only executes Python code but also conducts data analysis and derives insights from datasets.

In this section, we’ll explore how to harness the Code Interpreter for the following purposes:

  1. Performing Additional Data Analysis: We’ll use the Code Interpreter to conduct supplementary data analysis using the information within the financial statements.
  2. Extracting Data and Saving in CSV Format: Additionally, we’ll demonstrate how to extract data from the financial statements and save it in a CSV file.

Performing Additional Data Analysis

We’ll ask the assistant to generate a graph on the Tesla’s operational margin.

thread3 = client.beta.threads.create()
run3 = submit_message(FINANCE_ASSISTANT_ID, thread3, "can you draw a graph based on operational margins in the file?")
run3 = wait_on_run(run3, thread3)
messages = get_response(thread3)

Then we save the graph into a local file.

file_path = messages.data[-1].content[0].image_file.file_id

file_name = client.files.with_raw_response.retrieve_content(file_path)
output_file_name = "margin.png"
with open(output_file_name, "wb") as file:
    file.write(file_name.content)

We can display the graph in the notebook using the code below

from IPython.display import Image, display

# If your image is uploaded to the Colab environment
image_path = output_file_name
display(Image(filename=image_path))
Operating Margins graph generated by the Code Interpreter. Image by author.

Extracting Data and Saving in CSV Format

We can also use the Code Interpreter to extract financial data from the statement and save it in a csv file.

run = submit_message(FINANCE_ASSISTANT_ID, thread, "Can you extract the financial summary data et put it in CSV")
run = wait_on_run(run, thread)
messages = get_response(thread)

file_path = messages.data[-1].content[0].text.annotations[0].file_path.file_id

file_name = client.files.with_raw_response.retrieve_content(file_path)
output_file_name = "data.csv"
with open(output_file_name, "wb") as file:
    file.write(file_name.content)

Great! The code interpreter successfully extract the data we needed!

Data extracted from the financial statement. Image by author.

Hands-on Exemples on Custom Functions

Function calling empowers you to specify functions to the Assistants and have it intelligently identify the functions to execute along with their respective arguments.

In this example, we’ll create a Custom Function that can send an email to the user, such as sending a summary of the financial statement.

To achieve this, we’ll follow these four steps:

The 4 steps to add function calling capabitlity to the Assistant. Image by author.
  1. Define your functions

Begin by defining the function(s) you want to use. Here we’ll mock a function that send an email to the user and it requires 3 parameters: email, textbody and subject.

def function_send_email(email, textbody, subject="Financial Statement Summary"):
  #your implementation to be added here
  print("Email sent")

2. Define function interfaces in JSON Format

Let’s define the interface of this function in JSON format, so our Assistant can know how to call it.

function_send_email = {
    "name": "send_email",
    "description": "A function that takes in a user email, a subject line and body text and sends an email to the email address provided",
    "parameters":{
        "type":"object",
        "properties":{
            "email":{
                "type": "string",
                "description": "the email address of the user who receive the email"
            },
            "subject":{
                "type":"string",
                "description": "subject line of the email"

            },
            "textbody":{
                "type": "string",
                "description": "the body of the email."
            }
        }
    },
    "required":["email", "subject", "textbody"]

3. Update the Assistant with your custom functions

Integrate your custom functions with the Assistant.

assistant = client.beta.assistants.update(
    FINANCE_ASSISTANT_ID,
    tools=[
        {"type": "code_interpreter"},
        {"type": "retrieval"},
        {"type": "function", "function": function_send_email},
    ],
)

4. Adapt the wait_on_run function

During a Run, the Assistant can then indicate it wants to call one or more functions you specified. Then the Run will move to a required_action state . You are then responsible for calling the Function, and providing the output back to the Assistant.

We’’ll make necessary modifications to the wait_on_run function so that when it encounters a run in the ‘required_action’ state, it will call the function and submit the output back to the Assistant.

# Waiting in a loop
def wait_on_run(run, thread):
    while run.status == "queued" or run.status == "in_progress":
        run = client.beta.threads.runs.retrieve(
            thread_id=thread.id,
            run_id=run.id,
        )
        time.sleep(0.5)
    if run.status == "requires_action":
        tools_to_call = run.required_action.submit_tool_outputs.tool_calls

        tool_output_array = []

        for each_tool in tools_to_call:
          tool_id = each_tool.id
          function_name = each_tool.function.name
          function_arg = each_tool.function.arguments

          if function_name == "send_email":
            arguments = json.loads(function_arg)
            send_email(arguments["email"], arguments["subject"], arguments["textbody"])
            output = "Mail sent OK"
            tool_output_array.append({"tool_call_id": tool_id, "output": output})

        #Return results to the run operation
        run = client.beta.threads.runs.submit_tool_outputs(
          thread_id = thread.id,
          run_id = run.id,
          tool_outputs = tool_output_array
          )

    return run

Final Thoughts

In this post, we’ve explored the versatility of the Assistants API, using various tools to craft a robust AI Financial Analyst. The OpenAI Assistant, functioning as an intelligent agent, autonomously determines which tools and functions to employ.

The Assistants API can also be used in following ways :

  • Parallel Function Calls: calling multiple tools in a single Step
  • Multi-Assistant Thread Runs: single Thread with Messages from multiple Assistants

This technology can simplify complex tasks and provide valuable insights into financial data. But be mindful that GPT-4 is still much more expensive than GPT-3.5, and the use of OpenAI-hosted tools comes with additional costs.

Last but not least, the code snipets in this post are not specific to to our Financial Analyst at all. They can be easily adapted to any new assistant by simply changing the assistant ID. This demonstrates the versatility of the Assistants API. Feel free to customize the code to suit your needs!

As promised, please find the Colab notebook here.

Before you go! 🦸🏻‍♀️

If you liked my story and you want to support me:

  1. Throw some Medium love 💕(claps, comments and highlights), your support means the world to me.👏
  2. Follow me on Medium and subscribe to get my latest article🫶

Reference

  1. OpenAI Assistants API documentation
  2. How Assistants Work
  3. Assistants API Overview (Python SDK)
Artificial Intelligence
Machine Learning
Programming
Software Development
Recommended from ReadMedium