Hey everyone, Ralf here. One of the most common questions or requests that you guys have had in the past two weeks is how to programmatically upload files to your assistants using the OpenAI Assistants API. So in this tutorial I'm going to show you how easy it is to do with a few lines of code in Node.js. So let's get into it. So I have two windows open. I have VS Code and a terminal and all of the code that we're going to be walking through here today is available in a link in the video description along with a few steps of how to set this up. So make sure to go grab that in the video description. Before I explain the code I want to show you how it works in action. So I'm going to be running this code in my terminal here. So it's just node run assistant.js and what we're going to be doing is creating an assistant that is a murder mystery helper and then upload a file that contains the murder name and what we're doing here is just hit this and I've set it up in a way that if I don't already have an assistant it's going to create one but I'm saving the assistant information in this assistant.json file. So if I run this code again we will be reusing an existing existing assistant so you don't have to create one over and over and over again. But back to this. So what we're being asked here by the script is what is it that you want to do? Do you want one chat with the assistant or two upload a file? So let's just fast forward to the file. We're going to be selecting two. Enter your choice. Number two, enter the file name to upload. So I have this clues.txt that contains the name of the murderer. So let's say clues.txt and what the script does is that it uploads it to OpenAI and then attaches it to our assistant. So now our assistant actually has a file that it can use. So let's go ahead and try it. So do we want to perform another action? Yes. And I want to chat with the assistant so I'm going to press one. And what is your question? Let's just jump to it. Who's the killer? And without the file it would have no clue what the killer is but now it knows that it's Rick Sanchez because that's what clues.txt tells it. So let's just exit all of this and walk you through it and I'll run it again at the end of the script or sorry end of the tutorial just to show you how it works with uploading several files and reusing this assistant.json. If you're mainly interested in the file upload bit and you've already used the Assistants API before, check a timestamp or a chapter in the video to skip ahead to that portion. But for everyone that is new to Assistants API, I figured I'll just explain all of the code in here. So we are importing a couple of dependencies here and all of these again are available and explained in a link in the video description. But we're using .env because we're storing our OpenAI API key as an environment variable here. We're using the OpenAI npm package. I'm using fs to read and write files such as the assistant file, the clues.txts, etc. And then we're using readline to allow us to do this back and forth between the user and the script. We're setting up an OpenAI connection right here reading the OpenAI API key from this environment variable that we've created here. And then we just have this ask a question function where we're using readline to to get input. And then the meat of all of this lives in this main function. So I'll walk through that but I just sort of want to mention that this gets called at the very end and this is what allows us to keep talking to the script as we go. So this main function will continuously run until we exit the script. And what it does is that it just starts with setting this assistant id as an empty variable. And then we're going to be having this assistant file path that we say is assistant.json. And what I use the assistant.json for again is just storing if we have an existing assistant. We're going to store the information in that so we can reuse that so we don't create a new assistant every time we run this script. So what we're doing is just checking does that already exist? If so let's use it. If it doesn't exist let's go ahead and create an assistant with the OpenAI API and then store that in a file and continue to use that. So that's what we're just doing right here starting with checking. We're doing a try here checking if we can read this file. If it doesn't exist it will error and we'll go here. But if the file exists we're just going to go ahead and read all of this data store it in assistant details. We're going to read this assistant id and store it in the placeholder that we just created and we're just going to fetch it from right here. And this is what we get back from the OpenAI API if we create an assistant. So we need that later when we call the OpenAI API to create conversations and files essentially. And then we just log and say hey we have an existing assistant let's use that. But again like the first time I ran this script we didn't have an assistant so we're just going to say okay no existing assistant detected creating a new one so that's what you can see right here. And then we're creating a config variable where we're storing the input so that we want to send to the OpenAI assistant creation endpoint. So it's the name of our assistant I named mine murder mystery helper instructions as you're a murder mystery assistant helping solve murder mysteries you can change these obviously. Then for tools I'm here only giving it the retrieval tool this is required if you want it to read files that you give it so you at least have to have this. But you can add code interpreter and browsing as an example and then model is just which model is going to use and right now I think the only one that exists is this GPT-4 11.06 preview. And then we're going to send an API call to OpenAI to create this assistant so we're just going to const assistant and make it awake.openai.beta.Assistants.create and we're just passing in this assistant config which is everything that OpenAI needs to create assistant. And then we're creating this assistant details variable that includes the assistant config and assistant ID right here and then what we're doing with that is just creating this assistant.json file right here so we have it for future use. And then lastly we just set the assistant ID to the assistant ID that we got back from OpenAI and which is also stored in our JSON because we need it later. So now we either use an existing assistant or we created one now we can go ahead and start using it. So what the script does is just say hello there I'm your personal assistant you gave me these instructions so this is what you can see right here and then we go ahead and create a thread and what that is in OpenAI is an assistant can have several threads and you can think about threads as conversations. One assistant can have several threads or several conversations and each conversation can have several messages so think about messages as you asking something you get a response from the assistant you ask something you get a response and all of those sort of back and forth are stored in one thread. So what we're creating here is just a new thread with the assistant that we're now going to start fill up with questions and answers and in order to have this ongoing conversation in our script here we're going to be using a while loop that will continue so long as this keep asking is set to true and it's set by true to true by default here so that means that we're going to run this while loop and this while loop is going to start off by asking what do you want to do you want one chat with assistant or two upload a file so it's what you can see here and then the user needs to input their choice either one or two and I don't have any error handling around anyone saying three or anything else so you can add that if you want now if action is two we're going to start uploading a file and that's probably why most of you came to this video so we're asking this enter the file name to upload and we're storing that file name in this file name variable now I assume that the file exists in the same folder as your script and exist assume that the file also exists if you provide a non-existing file name there's no error handling for that so that might be something that you want to add to your script if someone else other than yourself are using it so we're going to take this file name and then we're going to upload that file to openai so what we do here is that we cause the file we use the openai.files.create endpoint we're passing in the file here and then we have to set this purpose parameter to Assistants you have to do that or otherwise your assistant won't be able to use the file next what we're doing is that we need to tell openai that this file that I just uploaded I want this assistant my assistant to have access to it and we're doing that by updating our assistant so we're going to call this openai.beta.Assistants.update we're passing in the Assistants id of the assistant that we're using and then we're passing in our file id and we actually need to not just pass in our one file id because let's assume that we have uploaded historical files if you just pass in the file id right here you're going to be overwriting other files and just say this assistant only has this file id that I created so what I'm doing here is that I'm also passing in any existing files so I'm passing in the new file id and any previous files that I've uploaded via my script and the way that I have this existing file ids here is that I store all file ids that I upload in the assistant json so when I uploaded the clues.txt here I got an id back I stored it in this assistant json so next time I go ahead and upload a file which I'll do in a minute we're passing in this existing id along with the new id to make sure that openai has an array of all the file ids again if you only send this you're going to be overwriting assistant for existing file ids and only use one file so that's what we're doing right here so now our assistant has this file attached to it and I'll show you what this looks like in the openai portal as well and then lastly we're just updating our file here to make sure that we're storing this file id that we get back from the openai api in our file once we've done that we just console log this file uploaded and successfully added to assistant so for anyone that wants to upload files to Assistants this is really what you need to know it's really that simple Assistants.update and the file id now if you are new to the Assistants api I'm just going to show you the rest of the script here if that's something that is useful now we're just asking again do you want to take another action I said yes right here we then select chat with assistant and by doing that we choose action one and then we're just going to continue asking here so we ask what is your question and now we get back to the thread or the threads so we have created a thread previously we've stored the thread id here in the thread.id and now we're going to be sending our user question to openai so I asked who is the killer that gets stored in this user question we're passing that into the openai.beta.threads.messages.create passing in the thread id the role which is the user and the user's question and then the way that openai's Assistants api works is that you don't just get a response back similar to the chat completion endpoint if you use that you have to create what's called a run because this is going to run in the background and you're not going to be told when the answer is ready you actually have to do some pulling so the way that that works is that you create what's called a run you pass in the thread id you pass in which assistant that should be getting this and then this run gets triggered in openai's backend and now you have to start asking is this done yet is this done yet do you have an answer for me so we set up a run status here where we're calling openai.beta.threads.run and we're trying to retrieve the status of this run is it completed yet when we run this the first time it's going to be no it's not completed because it's just been a millisecond since you send the or created this run so openai can start sort of processing your question so we set up this pulling mechanism so while run status is different than completed we're essentially going to be every once a second we're going to check is the run check what the run status is by trying to retrieve it for this thread id and run id and there are other statuses than just completed it can either be completed failed cancelled or expired so we just make sure that we also look for those and if either of those happen we're just going to break and go back and ask you to provide another question but once the run status is completed we now have an answer so we're going to fetch that using the openai.beta.threads.messages and we're going to get a list for the thread id so again a thread can include several different messages if you ask several questions you're going to have all of those and they're all provided to you in the api response so you don't have to keep state of previous questions but we only want to show the answer to the most recent question so we don't need all of that so in this little script right here we're just fetching the most recent assistant answer we don't care about previous answers we don't care about the user question we already have it here we just want the answer to the most recent question or the message so we just fetch that here and then we just go ahead and provide it as a console.log right here and then once that is done we're just going to ask do you want to ask another question and you can say yes or no if it's yes you just ask another question if it's no we pop down to the level above which is do you want to perform another action do you want to upload a file do you want to chat if that's no we just exit the script and that's all of it right here so let me show you once again how this works and then we'll just look at what this looks like in the openai platform as well so i'm going to go ahead and run node run assistant again and you can see the difference here it says existing assistant detected because now we created one previously so we're going to be using that we're not creating a new assistant now i'm just going to go ahead and upload a file again just to show you something so i'm going to upload the same file i'm going to upload clues.txt and you might say well you already did that like will that work yes and here's an important point this will work it will upload it and openai doesn't really keep track of like hey this is the same content that you provided to me previously it doesn't really care about that so i'm going to flip over to my browser here we have a list of assistants so here's the murder mystery helper that we created moments ago if i open this you can see that it actually has two files and it's currently showing the ids the names will load in a minute and that's because it doesn't keep track again like both of them are called clues.txt they have the same contents because on our computer it's the same file but openai doesn't understand that we have just uploaded two different files and said those two files should be used by this assistant so that's worth noting that you can upload the same file several times and openai won't give you an error and if you ever want to clean up assistants you can just go ahead and delete them by clicking the three dots and hitting delete here and similarly any files that you have uploaded you can do this programmatically it's not in scope of this tutorial but you can just head over to files here you can see we have two clues.txt that were uploaded a few minutes in between and this allows us to delete them if we want to but that's it for this tutorial now you know how to upload files to openai programmatically and how to give assistants access to use those files i hope that this was a useful starting point for you if it was please consider giving this video a thumbs up and also consider subscribing to the channel i will be putting out a lot more openai tutorials in the future but thank you for watching this one and maybe i will see you in a future video bye