Using the OpenAI Assistant API

Fateh Ali Aamir
4 min readDec 1, 2023

In the last year, ChatGPT has taken the world by storm. It then allowed us to be part of that storm by using the Chat Completions API to link our apps to it’s model and work with it on our ends. Now, it is giving us the capability to create our own storms. To put it in simpler words, we now have the power to create our own GPTs that our tailor-made to our needs. Introduced on the OpenAI DevDay held on November 6th, 2023, the OpenAI Assistant API is officially released.Let’s dive in.

We’ll be using Python to build our own custom GPT. First and foremost, you will need to plug in your API Key from OpenAI. Once you do that, we will start up our client and we’re ready to go!

self.client = OpenAI(api_key="[API KEY]")

Creating An Assistant

Let’s create a function to create our assistant. In this function we will be calling the create function from OpenAI and pass it a few parameters. This function returns an assistant object which also has various attributes. From that object we will then return the assistant ID.
Parameters:
1. Name: The name that you want the assistant to have.
2. Instructions: This is the prompt that describes who your assistant is.
3. Tools: These are supporting functions like a code interpreter.
4. Model: This parameters describes with OpenAI model you’re using.
5. File ID: This is an optional parameter used when you have custom files.

def create_assistant(self):
assistant = self.client.beta.assistants.create(
name="[Assistant Name]",
instructions="[Instructions]"
tools=[{"type": "[tool name]"}
model="[model name]",
file_ids=["file-id"]
)

return assistant.id

Creating A Thread

A thread for an assistant is basically a unique session you have with the assistant. Each and every thread will be everlasting and it will have all of the context that has been passed onto it through conversation apart from the data fed to the assistant. Each thread is an independent chat just like in ChatGPT. You will have new threads for every new session and the context is not shared between threads. The thread function returns a thread object and from that, we will return the thread ID.

def create_thread(self):
thread = self.client.beta.threads.create()

return thread.id

Sending Messages

Sending a message is pretty easy. We just need to define a thread ID, the role and the content for that message. For now, only the “user” role is available for the assistant, unlike the Chat Completions API where we can send in “system” or “assistant” roles for context as well. To put it more simply, what’s happening here is that we’re adding a new message to the thread and after that we’ll run the assistant to process our query and fetch a response.

def send_message(self, content):
# Send a message to a thread and return the message object
message = self.client.beta.threads.messages.create(
thread_id=self.thread_id,
role="user",
content=content
)

return message

Running the Assistant

Now we’re getting towards the fun part. Once your assistant and your threads are set, you will need to run it. You will pass in the assistant ID and a thread ID to the run function. This function returns a run object. The run object can be very useful. It is important to understand that a ‘run’ with the assistant describes the back-and-forth exchange between the user and the assistant. Each time a message is sent, the run starts. And when the message is returned, the run is completed.

Now, you cannot interrupt a run by sending another message during that time so for that we use an attribute in the run object called status. Once we send a message and call the retrieve function, we keep the program in a halt state until the processing is complete, the run is completed and we’ve received a response.

def run_assistant(self):
# Check if a thread exists; if not, create a new one
if not self.thread_id:
self.create_thread()

# Run the assistant and display responses
run = self.client.beta.threads.runs.create(thread_id=self.thread_id, assistant_id=self.assistant_id)
# Check the status of the run until it's completed
while True:
try:
run = self.client.beta.threads.runs.retrieve(thread_id=self.thread_id, run_id=run.id)
if run.status == 'completed':
break
# Wait for some time before checking again
time.sleep(5)

# Display responses
return self.display_messages()

Displaying Messages

When we have to display messages, we call in a list of all messages from the thread and it returns a messages object. The message object has many attributes but we’re only concerned with the role and the content. Additionally, we also need to run a negative for loop to display all the messages in the correct order.

def display_messages(self):
# Displaying responses
messages = self.client.beta.threads.messages.list(thread_id=self.thread_id)

for message in reversed(messages.data):
print(message.role + ": " + message.content[0].text.value)

This new update from OpenAI is phenomenal and it can potentially change the world as we know it. We are in the midst of an AI revolution and we need to be ready for anything. With upcoming updates from OpenAI, we can evolve our assistants into something more. They will be able to perform our tasks or even replace us entirely when it comes to real-world responsibilities. There are exciting (and maybe frightening) in store for all of us. Let’s sit back and enjoy the show.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Fateh Ali Aamir
Fateh Ali Aamir

Written by Fateh Ali Aamir

23. A programmer by profession. A writer by passion.

Responses (3)

Write a response

sleep(5) isn't this too big

Not working, sorry

This was very helpful. Thank you for sharing!