ChatGPT Course – Use The OpenAI API to Code 5 Projects

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Welcome to this exciting video course brought to you by the renowned course creator Ania Kubow. In this comprehensive ChatGPT course, we'll dive deep into the world of the OpenAI API, exploring its diverse capabilities and potential applications. Throughout this journey, you'll master the ins and outs of the OpenAI API, starting with creating your very own ChatGPT clone, which is a powerful language model that can generate human-like text based on your specific needs. Next, we'll dive into the fascinating realm of DALL-E, an AI-driven image generator that can produce visually striking and imaginative images with just a few lines of code. Finally, you'll create a SQL generator, a game-changing tool that can help you generate and optimize complex SQL queries in no time. With Ania's engaging and hands-on teaching style, you'll find yourself immersed in the world of AI, learning not only the theory, but also practical techniques that can be applied to real-world projects. By the end of this course, you'll be equipped with the knowledge and skills to harness the power of the OpenAI API to revolutionize your work and open up a world of creativity and innovation. Welcome to this extensive ChatGPT course. If you're a developer looking to integrate natural language processing into your applications, you've come to the right place. ChatGPT is a powerful language model created by OpenAI, capable of generating human-like text responses to a wide range of prompts. With API that powers it, you can integrate cutting-edge technology into your applications and unlock a whole new world of possibilities. My name is Ania Kubow, and I'm a software developer, as well as course creator here on freeCodeCamp, as well as on my own channel. In this course, I'm going to walk you through each section of the OpenAI API documentation. I'm going to show you how to access the API, use its various endpoints, and use them in various real-life projects that we will be building together, including this ChatGPT clone in JavaScript, a version in React for comparison, an AI generator in JavaScript, as well as one in React utilizing the OpenAI Node.js library, as well as an AI SQL query generator that will generate SQL for you based on the prompts you give. By the end of this course, you'll be able to confidently take the OpenAI API and integrate it into any application that you build to fully utilize its powerful natural language processing capabilities. If you want to skip to a section, then please feel free. We've given timestamps in this course for you to be able to navigate from one to the other. Just be careful, as we will be building our knowledge from the previous sections and using it in the sections that follow. Okay, so what are we waiting for? A basic understanding of JavaScript and React is necessary for this course, but if you don't have it, please feel free to follow along anyway and then fill in the gaps later on. Just like most APIs, the OpenAI API uses API keys for authentication. In this section, I'm going to show you how to get your own API key for when it comes to communicating with the API from applications that we will be building. Remember, make sure not to share your API key or publish it somewhere public. This is because if someone takes it, they could potentially use up all your free credits or rack up loads and loads on your credit card. If you have a credit card attached to it, this also includes exposing any client side code. By this I mean building an app without a backend and deploying it onto the internet. The code in this case will be visible simply by inspecting it like so someone will then be able to go and take it from here for the road use. To use this key safely, requests must be routed through a backend server where your API key can be securely loaded from an environment variable or key management service. Okay, so let's look at how to get your own API key as well as generate new ones if you need. Okay, so let's do it. Let's start off by getting our API keys. So first off, just start off on OpenAI.com and make sure you're signed in and under menu, go ahead and click under the developer portal and just click overview. This should take you to platform.openai.com/overview. Perhaps the UI has changed, but essentially this is where you need to be. Next, just go ahead and click on your username. As you can see here, my username is freecodecamp-editorial. I'm just going to go ahead and click on that and view API keys. And there we go. So as you can see here, there is already one secret key. Let's get to creating a new one. So all I'd have to do is click on this gray button right here. And I can choose to name this if I wish. So let's go ahead and name this my demo key, and just create a secret key. And there we go. Now don't forget to copy this and save it somewhere safe. Why? I'm just going to go ahead and click done. We cannot view that API key anymore. So if you didn't save it, well, you're going to have to create a new key. So let's go ahead and delete that one because I didn't save it. So let's revoke it. And all you're going to have to do is click on this little button right here and revoke the key. And let's create a new one. So I'm just going to create a new key again. And let's call this my demo key again. And this time, let's create the secret key, copy this, save it somewhere safe, and click done. Now, if you are worried that someone has stolen your API key, or perhaps you might have published it out onto the internet, you can revoke it as we just saw. So you just click the revoke key, and then that API key will not work anymore. Okay. And why do we not want it to work anymore? Because if someone has indeed stolen your API key, they can potentially if you click under usage right here, use up all your free credits. So as you can see here, here are the free credits that we have used for the month, we don't want someone taking our tokens, right? Or worse, if we have a credit card attached to under billing, you can attach payment methods, they can also potentially rack up loads and loads on your credit card bills. So keep this API key safe. The OpenAI API is powered by diverse set of models with different capabilities and price points. At the time of writing, the newest we can use is GPT-4. It uses a set of models that improve on GPT 3.5 and can understand as well as generate natural language or code. We will be using this model as well as its previous versions the most as it's the most universal. Others of note are DALL-E, which is an AI system that can create realistic images and art from a description in natural language. We can make requests to create numerous images of a certain size, edit an existing image or create variations of a user provided image if we wish. We will be using this in our projects that are coming up soon. There is also WISPR, which is a general purpose speech recognition model. It is trained on a large data set of diverse audio and is also a multitask model that can perform multilingual speech recognition, as well as speech translation and language identification. In fact, here is a full list of models that are currently to our disposal. Let's get to understanding some of these better next. Now that we have our API key and have understood the models that are available to us, let's get to writing some requests. These two things are super necessary for this next part. So make sure you have both. First up, we're going to look at text completion. With text completion, we can generate or manipulate text. By this, I mean it was literally built to complete your sentences. So if you write Oscar Wilde, be yourself, everyone else is, it will return already taken with high probability. You can also ask it to complete from nothing based on text prompts. I can write something like come up with a name for my friend Darius's pizza shop, and I will come back with this. Now it is likely you'll get a different completion each time, even if your prompt does not change. This is because the API is non deterministic by default. By this, I mean it is not possible to guess what will happen. We can actually change this by setting a temperature to make it more deterministic. But we will cover that when the time is right. So let's try it out. Here's the endpoint we will be using for this. It is a POST request. For those of you who don't know what a POST request is, now will be the time to check out a tutorial on HTTP request methods to fully get the most out of the next steps. Or if you are feeling adventurous, please carry along anyway and fill in the gaps when you want to. Now there are a few things that we can put in our request body along with our POST request. And here they are. The only one that is not optional is the model that we are going to use. So let's whack that in. I'm going to go ahead and use text of Vinci 003 for this demo. As a reminder, here are some of the models we can use. Although keep in mind that not all of them can be used for text completion. Next, we are going to put in a prompt. This is essentially a string or an array that we are going to pass over to the API to generate completions for. In this case, I'm going to pass a string of Hello, how are you today? We can also choose to add a suffix which takes strings, which comes after a completion of inserted text. But I'm not going to do that for this demo. Next up, we can optionally add max tokens. This will take an integer that will represent the maximum number of tokens to generate in the completion. Tokens are what all the models use to process text. They are essentially common sequences of characters found in text. The models understand the statistical relationship between these tokens and Excel are producing the next token in a sequence of tokens. I know this is hard to comprehend. So let's look at an example to understand how the API would tokenize a piece of text as well as see the total count of tokens in that piece of text. So let's go ahead and put in the string of Hello, how are you today? You will see seven tokens are used here according to the API. Now let's try another one. Let's try what is the meaning of life and can you write an essay about it? Now this is of course a little bit more complex. So you will see the number of tokens that were used were a total of 15. As a general rule, one token generally corresponds to roughly four characters of text for common English text. This translates to roughly three quarters of a word. So in other words, 100 tokens equals roughly 75 words. The token count of your prompt plus max tokens cannot see the model's context length. Most models have a context length of 2048 tokens except for the newest models which can support 4069. Next we have the option to put in temperature as a number. We can write a value from zero to two. Higher values like 0.8 will make the output more random while lower values like 0.2 will make it more focused and deterministic. And as an alternative, we can also use top P, which will use nuclear sampling as opposed to sampling with temperature. It is recommended using this or temperature or not both. In this case, the model considers the result of the token with top P probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. Next we have n. n allows us to set how many completions to generate for each prompt by pausing an integer value. Doing this will understand we take more tokens. So just keep that in mind. We can also pass through a user which will represent our end user to help monitor and detect abuse. So these are the most popular ones used. I'm just going to show you the other ones briefly to show you they exist but not going into them in any detail. Okay, so all of these along with ones we just covered can go into the request body along with our post requests. And the only one that is required is the model that we're going to use. Got it? Good. Let's try it out. Okay, so what I've done is just set up a super simple project. I have done this in my code editor, I've just created an index HTML file with some boilerplate code. And then I've linked up the app js file using this script tag. So that's all I've done. Next, I've just created that app js file. And this is where I am going to write that request, it's going to be a post request to the endpoint that we saw passing through all the options. So let's do it, I'm going to do it this way first. And then I'm going to show you how to do this with a cowl command. So first off, well, let's actually do this all in a function. So I'm going to call this function fetch data, just like so. And this is going to be an async function, as we're going to be using the await keyword in here, because we're going to be dealing with the fetch API. So we're gonna have to wait for this to get resolved. So we're gonna have to await the response of this. Okay. And then we're going to save this to whatever we want, let's save it to the const response. Now, I'm just going to minimize this for us, we can see this a little bit better. Now, the URL that we need, or we can just take this from the documentation, it's going to be this, right? So just make sure yours looks the same, and you're not going to check completions, we're just going to the completions endpoint this time. Next, we're going to pass through our options. So my options, well, we're going to pass through the method, as we know, this is a post method. And now we're going to pass through some headers as well. So the headers that I am going to pass through, well, we're going to have to pass through our API key. And for that, I'm going to use authorization. And now because we are well, you can put in the string directly in here, but most of you will probably want to save your API key somewhere safe. So use back ticks so that we can use text essentially or a string and then put in some code and to put in code, we use this syntax. So you get your dollar sign and your curly braces. And then we're going to put in our API key here. So this is going to be a const. Let's define up here const API key. And just go ahead and paste your API key in here as a string. So that is my one that I will be revoking, and we're ready to carry on. Now, let's also define our content type. So content type, and we're going to be working with JSON. So we're going to do application, Jason, because we're going to have to pass through a body of stuff. And that stuff is well, it's the options that we saw. So here's our body, I'm going to wrap it in JSON stringify, just like so, and create an object, my object is going to hold everything we want to pass on to OpenAI. And that is the model. On this occasion, I'm going to use text dot Vinci 003. When we get to doing the chat completions, we will be using chat gt before and chat gt p 3.5. But for this one, we can just go ahead and use text eventually, because we can't use the others. Now I'm going to use prompt. And let's just go ahead and hard code a prompt. Hello, how are you today? Okay. Just like so. And we can also pass through the max tickets if we wish. Okay, I'm going to go ahead and do it as that's what we saw in the example. And I'm going to go with seven. So the only thing that is required are these two. And this one is optional. Just make sure that is max token seven. Okay, so those are all options. Okay. And now we're going to get the response. And we're going to get it to Jason. But oh, this is also an async method, which means we need to wait for that to come back. And let's save it as something I want to save as data. And now let's just console log data. Okay, that's all we're going to do. So let's call this function. So we just want this to be called when we open up the web page. So let's go ahead and copy the path, the absolute path to this is in like so. And now I'm just going to inspect this page and look on the console log. And today, that is essentially our data. That's what we're console logging out. And if you look under choices, so there's objects you use dot notation to get this, you'd go dot choices, and you go into the array. And you can see the text that has come back it says, I'm doing well. Great. So that is how you would do it in JavaScript. This is what we're going to be doing in one of the projects. We're also going to be doing this in the back end where we store API keys safely. However, for those of you who don't really want to build a project, you just want like a simple response in a matter of seconds, I'm going to show you how to do this with a call commands next. Okay, so maybe let's just get rid of that and get up my terminal. Okay, so here's our call command. As you can see, we've got the endpoint right here, make sure yours looks the same. So it's not going to force that chat or anything like that. We've got the content type, we've got the authorization. So let's go ahead and replace that API key right here. So I'm just going to delete all of this, including the dollar sign. And I'm just going to paste mine in like so. So that's what yours should look like. We've got a model here, we have say this is a test, let's go ahead and replace this with Hello, how are you question mark, we've got the max tokens that we also have a temperature. So let's go ahead and run this, I'm just going to hit enter. And there we go. So this is essentially what we saw coming back to us in the browser, we've got I'm doing well. So two ways to do this, please play around with these, have fun. And when you're ready, let's move on. OpenAI models can do pretty much anything from writing original stories to performing complex text analysis. Because they can do so many things, you have to be explicit in telling them what they need to do. Showing and not telling is often the key to writing a good prompt. Here are three basic guidelines to creating effective prompts. So first off, we have show and tell, make it clear what you want, either through instructions, examples or a combination of the two. If you want the model to rank a list of items in alphabetical order, or to classify a paragraph by sentiment, show it that's what you want. Next up, we have providing quality data. If you're trying to build a classifier or get the model to follow a pattern, make sure that there are enough examples. Also, make sure to proofread your examples. The model is usually smart enough to see through basic spelling mistakes and give you a response. But it also might assume that this is intentional and it can affect the response. And finally, check your settings, the temperature and top B settings that we covered earlier control had deterministic the model is in generating response. If you're asking it for response where there's only one right answer that you'd want to set these lower. If you're looking for more diverse responses, then you might want to set them higher. It is also worth knowing that the number one mistake people use with these settings is assuming that their cleverness or creativity controls. Okay, so those are the three guidelines you can use for writing effective prompts. Please have a go at trying them out and seeing if your prompts are actually getting better responses by applying these three basic guidelines to them. And once you're ready, let's carry on. Okay, so by now we would have looked at text completions as well as how to write effective prompts. So let's get to the media stuff, we're going to look at chat completions. Next, chat completions will essentially have a whole conversation with the OpenAI, we are going to do so by using the GPT 3.5 turbo model, or the GPT for model to a different endpoint, or specifically to the OpenAI chat API. With OpenAI chat API, we can do such things as write code, suggest text for an email, create AI chat agents, translate languages, suggest topics for talks, and so much more. We will be using this API for our upcoming projects. This is because it can do pretty much what the text completions can do, but of course, take it one step further by initializing a whole conversation and chat. So we're really covering all the bases by using this. And not only that GPT 3.5 turbo performs at a similar capacity to text DaVinci 003 that we use in the text completion part of this course, but a 10% of the price per token. So it makes sense for us to use it really. Luckily for us, a lot of what we learned in the text completion part of this course will be applied to you too. So as previously, we will need our API token and the model we want to use. For this, we will be using the following endpoint and making a post request to it. So as you will see this time, it's forward slash chat forward slash completions. Next, we put in our token as well as the model we want to use. So I would put in my token and the model of GPT 3.5 turbo or GPT for these two things are required. What is also required in this case is the messages. Messages take an array of objects in a specific chat format to generate chat completions. Here's an example of the array with an object of the specific format in it. It has a role and a space with a prompt content. Outside of these required fields, all the rest of these are optional. I will not go into them again as we already did this in the text completion part of the course. If you would like a refresher on what each of these mean in more detail and how they can be used, please go back to the text completion section not far behind this. Okay, so here we have our request. Let's give it a while. Okay, so once again, here is my project, I've just created two files, an index HTML file like so, with a script tag. And I've linked my app.js file right here, which is going to hold our JavaScript. And our JavaScript is how we are going to essentially make a fetch request, a post request to the OpenAI API. So let's do I'm just going to minimize this. And once again, let's write a function, I'm going to call the function fetch data just like so. And in here, we're going to use the fetch API, we're going to pass through two things. One is going to be the endpoint and the second is going to be our options that we're going to pass through with that request. So the fetch keyword will is an async method. So we're going to have to use the await keyword. But oh, we can't use await inside a function that is not async. So let's put that in right there. So two things we're going to have to put in, we're going to have to put the endpoint that's right. And the endpoint, as we know, is this right here. And the options that we're going to pass through, we're going to pass through the method. And that is a first method. The other thing we're going to pass through is the headers, because we're going to have to pass through our API key. So once again, let's put authorization, making sure to spell that correctly. And then I'm going to use backtick once more. So bearer, and I'm going to pass through some code. And that code is just going to be the const of our API key, which I'm just going to define up here. Because you know, if you're doing this on the back end, you probably want to keep that API key and a dot in the file, for example, like we will be doing in the project. Okay, so our API key, once again, I'm just going to paste that in, I'm just going to paste that in as a string for now. So that will now be essentially injected into here. So we've got a API key. Next, we need to define the content type we're going to be working with Jason. So I'm going to do application, Jason, just like so. Next, we're going to have to pass through the body and the body, well, we're going to pass through an object, we're going to wrap it in Jason, the string of files and Jason string file like that. So let's get that object, and just work it in like so. So what things we need to pass through to our API, where the first one is the model, let's go ahead and work with GPG for this time. And we're going to pass through the messages, the messages, this is different than the prompt that we saw before, it's going to be an array. And each message is essentially an object, it's going to take a role, the role in this case, it's going to be the user, it's going to be us. And then the content, which I'm going to just hardcore us. Hello, for now, we can pass through as many messages as we want. Remember, this is a chat. So if you want to pass through more messages, you can do just like so. So if I want to say hello, how are you in two separate messages that I can, that is an option, I'll be showing you how to do this in the project part of the section. For now, let's just pass through one message. So once again, that is my one message represented by this object, which has these two things in there. Okay. So just so this is more readable, I'm just gonna put it like so. And that is all we need to pass through. So those are all our options. So let's wait for this and save it under response, and then get the response. So right after this has done its thing. So down here, and let's get its JSON, well, oh, this is an async method. So we're going to use the await keyword and await that JSON, let's save it under data. And I'm just going to console log that data. So let's call this, right? I'm going to get this and away at the bottom, let's just call this and let's open this up in our browser. So I'm going to copy the path, copy the absolute path, paste that in, inspect the page, go to the console log, and there's our object. And those are our choices. So we get an array. And then we see the messages that come back. This time, the roll is from the assistant, okay, because we're the user. And this time, the assistant is saying, Hello, how can I help you today? Great. So we're already starting a chat. This is wonderful. And once again, for those of you who don't really care about, you know, building on app, you just want something quick, let's look at the call command to do so. So here is the call command. Once again, let's just go ahead and make sure that URL is good. That is correct. And let's replace this API key. So I'm just going to go ahead and delete all of this, including the dollar sign, let's paste in that API key. Let's also replace this, let's go ahead with gpt four. And then we can have hello, sure, let's go ahead and hit enter. And amazing. So here we have the same thing. Here's our content from the assistant. Remember, we're the user, this is the assistant. And it's saying Hello, how can I help you today? Great. Great. So now that we have understood how to use track completions, I'm going to use this API and our next two projects. The first project is going to be more painful beginners, where we build out a simple JavaScript project in JavaScript, HTML, and CSS. And we use the fetch API in order to fetch data from this API using the request that we just built. However, as we now know, this will not be secure. This is because this is a front end project. Okay, so if you do choose to build this, make sure to keep your API key safe and don't publish this code anywhere on GitHub or anywhere on the internet, it is for your personal use. Next up, we're going to graduate and build the same project but in react. Okay, and this will allow us to build out a back end more easily, which is why I'm choosing the react library to do this. And I'm going to take this project a step further by not only just storing the prompts on the left in the history, if we click on them, it will bring back the whole history of that chat and allow us to add more to it. So as you can see here, I am switching from each one, I can also add more text and switch back and so on. And that will be in there as well as create a new chat if I wish. Okay, so that's what we're going to be doing. Of course, I could have also built a project that has a JavaScript front end and a Node.js back end. But you know, you can't do everything. So these are the two directions I've chosen to take this project in for the course. Okay, so what are we waiting for? One last thing I'm going to say is that the react project does not use the OpenAI Node.js library, which does exist, because I wanted to take the exact same JavaScript project and recreate in react. However, we will be looking at the Node.js library later on in this course, when we build out an AI image generator. Hey, everyone, so great to have you here. And I'm going to be showing you the easiest way to make a ChatGPT clone using JavaScript. Okay, so JavaScript, HTML and CSS, this is a great project for those wanting to learn how to use API, specifically the ChatGPT API in a simple JavaScript project. Now this is just for demo purposes. Okay, we do not want to go and publish this code onto GitHub or deploy it. Because as we know, right in a simple JavaScript project without a back end or anything like that, you can't hide your API key. So you don't want anyone taking this API key, because if they do, they can rack up loads and loads of money on your account if you have a credit card or anything like that associated with it. So this is just for demo purposes. If you want to know how to build a ChatGPT clone with a back end, then I'm gonna be releasing the same video but building this in react with a Node.js back end. Okay, we can of course also have a JavaScript front end and a Node.js back end. But I think the React app will be way more fun to build. So what are we waiting for by the end, you will have this ChatGPT clone, which we will be able to build you in JavaScript, HTML and CSS, and then we'll be able to ask questions as well as have a history of all the things we answered before. So let's do it. Okay, so first off, we're just going to start a new project. I'm in WebStorm, so I'm simply going to select new project. And I'm going to select an empty project. So it's being saved in my WebStorm projects directory or folder on my computer. And I'm just going to call it JavaScript ChatGPT clone. And I'm going to create. So that's going to spin it up for me. And now I'm just going to add some files, I'm going to create a new file, it's an HTML file, let's call it index dot HTML, you don't really need to put that HTML extension in WebStorm, but I'm doing it here for those who are not using WebStorm. And then I have this boilerplate code set up. So if you don't have this boilerplate code set up, please copy it here. And I'm just going to do JavaScript ChatGPT, clone, clone, just like that. And of course, we also need to create some more files, I'm going to create a JavaScript file called app j s. And then also a style sheet. So I'm going to create a new style sheet. Let's call it styles, because it holds all our styles dot CSS. So there we go. That is what my project looks like at the moment. I'm just going to make that small. So what do we need to put in here? Well, first off, I'm going to create two sections, one for the sidebar and one for the main bit. This is actually not going to take much CSS and HTML at all. So I'm just going to create a section. There's my one section, I'm going to give it the class name of side bar. Okay, and another section, this one's going to be the main section. So I'm just going to give the class of main to differentiate me two sections, we can pick them out by their style. Okay, so what's going to go in our sidebar first? Well, in my sidebar, I'm actually going to have a button that says new chat, and it's going to clear our input, okay, our search input. After that, I'm also going to have a div. And this is going to hold my history. Okay, so all the previous commands that we wrote, and I'm just going to style up a bit. So I'm going to give it a class of history, like so, you don't have to use the same style names. But you know, for the sake of tutorial, maybe copy along, and you can change them later. Next, I'm going to create a div. And this is going to hold my nav items. So I'm going to give it a class of nav. And then for now, I'm just going to have a p element that says made by Ania, you can of course add as many elements in here as you want, you can put in links, and so on. But I'm just going to have this. And now in my main section, I'm going to have an h one element that says Ania GPT, because that's what I'm calling my clone. Then under here, I'm going to have a p element that is just gonna show the output of my search. So I'm going to give this the ID of output. So we can pick it out, just like so. So that's one tag and another tag. And after that, I'm going to have a div. And this div is going to hold a few things is going to hold the input and then a little button to submit our query, right? So I'm going to give this the class of bottom section, so we can pick it out. And in here, I'm going to have a div. And this is actually going to hold my input and my submit icon, essentially. So let's also give this the class of inputs container. And then in here, I'm just going to put in an input element as a self closing element, and a div. And this div is going to have the ID of submit. So just like that. Now under so this is a child of the main section, this is a child, this whole thing is a child, I'm going to also put a p element. And this is just gonna be some sub info. So let's give it a class of info so we can make the text smaller by picking out this element. And then I'm just going to put ChatGPT, this is just from the website itself, March 14 version. In fact, I'm just going to paste it so we don't have to write it all out. But of course, you can pause here if you want to have this full text right here. So that is what that text is going to say. Okay, so actually, now we are done with the HTML part, please pause here to have a look at it or slow it down. But essentially, that's it. Maybe if I zoom out for some of you, you can see everything that is everything. Okay, with the correct formatting. Wonderful. So at the moment, if we open this up and web storm, I can just click here. And that will bring everything up. And if I inspect the page, you will see that section that we made. So there's our section, there's the other section with all the stuff inside of it. Okay, so now let's get to styling up. The first thing we do is make sure the side bus on the left and the main section is on the right. And for that, we need to link up our style sheet. And I'm going to link up the JavaScript file while we're at it. For those of you who aren't using web storm, you can view this by getting the index HTML page, copying the path, copying the absolute path, and just pasting in here like so it's the same thing. Great. So let's carry on. So let's link up our style sheet. First, I'm just going to go link. And I'm going to use rel, I'm just going to minimize this style sheet, just like so. And then h ref, and I'm going to link this to the style CSS file, which is in the same place as this file. So we don't need to go into any folders or anything like that, we just get the file name. And like I said, let's also do the script tag at the bottom to link up our JavaScript. So make sure it's at the end. So after all these other elements have been read, then we want to read this script. And there we go. So great, let's get up our style sheet. So first off, I'm going to get the whole body. So the thing that everything is in. And I'm just going to get rid of the default styling by adding margin and padding zero, just like so. Next, I'm also going to give it a background color. Now this background color I actually picked out from the website itself. So there we go. That is it. That's our background color. And now so at the moment, it will look like this. But these two are still kind of on top of each other. I'm also going to change the font in the whole project. So by adding this star, like so that means everything, everything my whole entire project is going to have the font color of white, which is hash fff, okay, you could do three F's, but you know, this is a shorthand for six steps. So that's what I have done. So now the text will be white. And to make this section to the sidebar section and the main section appear left and right of each other, we're going to use display flex. So all I'm going to do is on the parent of both of those, which is the body, I'm going to just write display, flex and save this file. And there we go. So now the sidebar is there. And the main section is that wonderful, we still have a bunch more stuff to do. So let's carry on. I'm actually going to import a font while we hear that font is open sans. And for that, we're going to go here. And then we're going to go to Google fonts. Okay, and in Google fonts, I'm going to pick out the open sans font. So all I'm going to do is search open sans, click on it. And then I'm going to select a few we can select as many as we want. So let's go ahead. I'm going to select maybe all of these. So basically just not the italic ones, so that we have them to our disposal in the project. I'm going to choose to import them via the style sheet. So I'm just going to take this code in between these two style tags. And then in my project, I'm just going to paste in like so. Okay, so there we go. There's the semicolon at the end and all the weights to my disposal. And once that is done, that means I can now use the font family open sans. So font family open sans and then as a backup, I'm going to have sans Sarah. So if you didn't know which code to use, you can actually get it from here. Here's the CSS rule to apply that family. And you just get that one. Great. And that's it. So that just means that that font will now be applied to my project. Let's carry on. So now that we have done that, I'm also going to pick out any h1 elements in my project and assign them a different font size because I don't like the default one. So I'm just going to go font size 33 pixels, and a font weight. So we just import loads of font weights, I want to go with 600. And I'm also going to pad it out. So I'm going to use the padding property. And I'm going to say 200 pixels from the top and bottom and zero from the left and right. So that's a shorthand, okay, this is top, bottom. And it's the same as me writing this. But because there's repetition, I can remove it. And that will now be applied to the top and bottom, and this to the left and right. So if we look at it now, that's what it would look like. There's my h1 element. Great. Now let's actually pick out the sidebar. So I'm picking out an element with a class of sidebar that dot means class. As you can see here, we're looking here going, here's an element with a class of sidebar. So let's pick out the whole thing. So that's what I have done. Now I'm going to give this a different background color. Again, I have picked this out from the project. So from the actual website itself, and I'm going to say the width of this is going to be 204 pixels. The height is going to be 100 of the viewport height, so VH, so whatever the browser size is the height, I'm getting it. And I'm also going to make sure that everything inside is going to be set on top of each other with equal spacing. So I'm going to use display flex for that. I'm initializing flex box. So then I can use flex direction, okay, without this, this will not work. And I'm going to make sure that everything in the sidebar is a column. So like stacked over each other. So that's what I would use. So if I look at this now, you will see, okay, there's a button, there's basically everything in the sidebar. So this, this, this is stacked on top of each other. But what if I want them to appear equally spaced, right? So the nav bar is all the way at the bottom, this is kind of in the middle spaced out equally between the button and the nav bar. Well, I can use justify content space between. So now if I refresh this, there's our p element. That's who lets me be gone here. So there's our div with the nav class, there's our div with the class of history. And there's our button. So the spacing between all three is equal. And no matter if I change this, that space will always be equal no matter how big the browser is. So I like that. Let's carry on. Let's also now maybe style the main section. So the other section, once again, I'm going to use display flex. And I'm going to use flex direction column just to make sure that all stacked over each other. But this time I want to align items to the center. So I'm actually aligning them from left to right, because we've changed axis of display flex. If none of this makes sense, please do check out my full stack developer course where I go into this in a lot more detail, as flex box can be quite confusing. So that just means I've centered everything from right to left by using align item center. And we're doing it from this axis as we've swapped the axis by actually making them a column. So whatever direction we're going in, if it's a column, align items will be on the opposite axis. Great. So this is looking good. So far, let's carry on. I'm also going to use text align center to make sure that the text is in the center, which it is, but now the bottom part is as well, because at the moment is being aligned to the left. And once again, I'm going to use justify quantum space between just to make sure that they are also spread out equally, no matter how I make the browser that will always be at the bottom, and this will be pushed to the top. So I'm spacing everything out equally on this axis. Great. So I'm happy with that. The other thing that we need to do is assign this a height. So I'm going to go with height 100 of the viewport height. So now that text will always be stuck to the bottom because we're taking the browser height into consideration. Next, let's style up this text. So it's a bit smaller and more transparent. So we gave this the class of info. So let's pick out this whole element, the whole p element by the class name. So I'm just going to grab the class name of info. And I'm going to make the color of this a transparent. So I'm going to use our GPA, I'm going to go with white. And then I'm going to put 0.5 opacity. So to make it consistent, you might want to consider changing these to be RGB two, just so that we don't have hex colors and RGB colors in the same project. So I might leave that as something I will do at the end. Next, I'm just going to also change the font size to be 11 pixels, because I want it to be a bit smaller. And I'm also going to pad it out. I'm going to do 10 pixels packaging all around. So now my text will look like that. That is much more like the website. Wonderful. Let's carry on. I think next is also maybe style, what should we style next? I think let's style the input itself. So this thing right here. So I'm just going to grab the input element. I'm going to get rid of its default border. So I'm going to go with border none. And let's go with background color. Again, I think let's just use this color. So like a transparent white, I'm going to make sure that the width is 100% of the pound container, the font size is going to be 20 pixels. Let's pad it out. I'm going to pad out 12 pixels from the top and bottom and 15 pixels from the left and right. And just round off the edges slightly. So I'm going to do border radius, five pixels. And now I'm going to do border radius five pixels just to round off the edges. Don't forget to have that syntax right there. Okay, and finally, I'm just going to add a box shadow because who doesn't love a box shadow. And this time, the color I'm going to go with this RGB black, so that's black, I want to make it transparent. So I'm going to go 0.05, and add a here to give it opacity, I'm going to go zero pixels, x axis, 54 pixels, y axis, 55 pixels blur, we don't need pixels here for zero. So we're just going to get rid of that. I'm going to overlay it with another color. So actually, I'm just going to maybe copy this, as we're going to have the same color. However, this time, I'm going to go minus 12 pixels here, and then 30 pixels blur. And then again, the same thing. So I'm going to paste again, and this time I have 046. So I'm just overlaying different box shadows to get a desired effect that I want and zero 1213. And maybe let's have one more. So 0.09 this time, and this time minus three pixels, y axis, five pixels. So that is my whole box shadow and effect will be this. And if I type in here, that will happen, we can get rid of this blue line. In fact, I'm going to do that because I really don't like it. So I'm going to say that when the input is focused, we're going to do outline none. So now if we look in here, I have gotten rid of that so much better. Great. Now this input is stretched out 100% of its parent, which is the input container or the input container, I also want to be stretched out want to make it bigger. So let's grab the input container. So the element by the class name input container, and I'm also going to make that 100% width of its parent, I'm also actually going to assign a max width. So it's going to try to be 100%. But then it's going to stop at 650 pixels. Okay, great. This also means that the parent of the input container needs to have some sort of width assigned to it. In fact, we can go and actually get main a width. So let's go make sure that the main element is 100%. And now the child of main is bottom section. So if this is 100%, next, I'm going to get the bottom section. And also make sure that width is 100%. Great. And now let's center everything. So main already has display flex on it. So we're going to have to get the bottom section and make sure that everything in the bottom section is also aligned in the center. So let's use display flex. So I'm going to do display flex, flex direction, column, justify content center, align items center. Again, if flex box is something you haven't covered before, please consider checking out my full site developer course where we go into this in a lot more detail. So great. So now everything in the bottom section is also centered. How good is that? And if we kind of make this as big or small as we want, it will always be in the center. Wonderful. So let's carry on just a few more styling things to do before we can continue. So next, I'm just going to style up the input container and submit button. So for this, I'm going to actually go in here and put in a text symbol. So it's this little arrow right here that I've taken off the internet, that's a text symbol, you want to get your own, I mean, I'm just going to Google it so you can see, you can get it from here. So just copy that that is the URL that you would need. So now if I refresh this, there's a little text symbol. However, I want it here, right? I want it to appear on the actual input itself, which is why I put them both in an input container so that I can position them thanks to position relative and absolute. So let's give the input a position relative relative to the whole page. So we can use position absolute on these two things to position them based on the parent. So let's do it. Again, this is something that you can learn in my course. So input container. Let's give it a position of relative so that we can give the children a position absolute to position them. And I'm going to get the input container, or the element by the class of input container. And say that if an element with the ID of submit lives inside of it, that is the syntax for doing so. I'm going to give it a position of absolute. Okay. So now if I refresh this, that shows up here, and I'm going to position it in relation to the input container. So I'm just going to go right zero, so it should appear on the right zero. So if I save that, there we go. And I'm going to move up from the bottom 15 pixels. Okay, so the from the bottom of the parent element. So let's go bottom 15 pixels. So now that should appear right there. And again, it will move based on the input container. So the parent, the other thing I want to do is change the cursor so that it's obvious I can click on it. So I'm just going to add cursor pointer, just like so and save that. And now my cursor will change so that will appear that I can click on this. Great, we are so nearly done. I'm just going to start these things a little bit more. So the button, the history, and the nav container. So let's do it. So the button itself, I'm just going to give it a border of solid 0.5 pixels, and transparent white, so we know that's 255, 255, 255, 0.5, I'm going to go with opacity, and then the background color. Let's go with transparent border radius, five pixels, padding, 10 pixels and margin 10 pixels to space it out from everything else. So with that styling, this is what my button will now look like that is much more like the actual website. And the nav, well, I just want to line up above it really and to space out a bit. So I'm going to get the element that has a class name of nav, we could have maybe used the nav element. But you know, that is up to you. Okay, maybe let's just switch it out. Semantically, that would probably make more sense. So if we go ahead and get rid of this whole class, and just use a nav element instead, that is also an option. Okay, and that just means I can pick up the whole nav element. And I'm going to give it a border top of solid 0.5 pixels. In fact, it's going to be the same color as this. So let's pick that out. Oops, just make sure that's a 0.5. So now that will look like this, I've just added a line, and I'm just going to space it out. So once again, let's just add the same padding and margin that we did for the button. And finally, let's grab the element that has the class name of history, also give it the same padding and margin. And I'm also going to use display flex to make sure that anything I put into it, because I'm going to be putting stuff into it with JavaScript, it's going to be stacked on top of each other. So I'm going to use flex direction column. And I'm also going to make sure that takes up 100% of the height that it can. Great. Next, I know that I'm going to be putting p elements into this history. So we're going to be using JavaScript, essentially put elements in here, we'll be injecting elements with JavaScript, and those are going to be p elements. So I'm going to say that any p element that I put that lives inside an element with a class of history, so that is the syntax for doing so, I'm just going to make sure that you can point on it. So I'm going to put cursor pointer. And there we go. So our CSS is now done now time for the part that I'm sure you've all been waiting for. And that's using the ChatGPT API. So let's do it. So I'm just going to head over to OpenAI.com. Of course, you have to sign up, this will be a free service, I believe up to a certain amount. And I've just opened this up in a new browser, so we can differentiate. So here is the URL that you need to be in. As you can see, I am logged in is platform.openai.com docs and introduction. And if you go to API reference, all you're going to need to do is get your open API key. So under authentication, if you actually visit your API keys here, you can create a new key. So this is one I made before, let's go ahead and create a new one. So this is the thing that you need to keep safe, okay, because if you attach a credit card to this, someone will be able to take it and rack up loads of money on your credit card. Or even if you don't, maybe someone will use it, and then you will be able to use any free generations anymore. So keep this safe. And of course, we are putting in this in our project, but please don't upload this on to GitHub or share it with anyone. This is just for demo purposes. If you want to learn how to actually deploy this app, and keep your API key safe, then we'll do that in the next video where I show you how to make the same thing, but in React, by building out a Node.js packet. Okay, again, as I said, you can build out a front end in JavaScript and use a Node.js backend too. So both options are viable. Okay, so let's carry on. So once we have that API key, well, we're actually going to go back to API references, and we're going to look at completions. So click on completions, because this is the URL that we're going to have to post to. So that's what we're going to do along with parsing or along our open API key, thanks to an authorization header, and then as well as the text or the prompt that we want to pass on to the OpenAI API. So let's do it. I'm going to show you how. So in your app.js file, I'm going to save this as API key, I will be disabling this. So don't try to use it because it won't work. I'm just showing you this for now. I'm just going to put in this texture. So it's super obvious to everyone not to deploy it or upload it on to GitHub. Next, I'm going to write a function, this is going to be an async function. Okay, so you can write it like this if you want. Or you can use const, it's totally up to you, you can make it a function declaration, or just a function expression. That choice is yours. And I'm going to use get message, I'm going to call it get message, because that's essentially what we are doing. And I'm going to use try and catch to try do something and catch any errors. So this is the syntax for this. If you haven't seen it before, this is how we can make calls. Now, I'm going to hook this up to the submit button. So if we click on this div with the idea of submit, I essentially want to make that call. So let's pick it out. So what I'm going to do is go const submit button. So we're saving it as submit buttons, we can use it in our JavaScript file, I'm going to look in my document, look at my whole document for an element. So I'm going to use query selector, I'm going to look for something by the ID of submit. So that's what this will do, look at my whole document, and look for an element that has the ID of submit. So we can use it in our JavaScript file. So I'm going to get that summit button, I'm going to add an event listener and say that if I click on it, then I'm going to call the function, the async function get message. Okay, so that's what that will do. So for now, if I just console log clicked, and then let's go back to this, and click on this little thing, check our console, it says clicked. If I click it again, two, three, four, you'll see how many times we are clicking it. So that's all I have done so far. Now let's get to actually passing stuff on to the API. So what I'm going to do is, well, we're going to use the fetch keyword, right? So I'm going to use await fetch as an async method, which is why this is an async function, and we need to await for its response. So we're going to await it and await an async keywords live together. If I use await, that means that that function needs to be an async function. So again, check out my course, if this doesn't make any sense. Now I'm going to fetch, well, this is what I want to fetch on we could post request to this URL. So let's grab this URL, because we want to create completions, we don't want to, you know, create images or anything like that, even though we can, but not in this project, that's not what we're going to do. So this is the URL that we're going to do is going to the chat and the completions. Okay, so make sure to have that one right there. Chat chat completions. This is the full URL. And it's a post request. And this we're going to use this, okay, in order to create our own post requests. So we're gonna have the content type, we're gonna have the authorization, the model and the messages. So let's go ahead and do it. Let's create that data, that information. And I'm going to define it under options. So let's define our options, const options, and we're just going to literally be taking that information. So what I'm going to do is pass the methods, we know it's a post method. As we just saw that making sure that is like this. And we're also going to pass through the headers, which we also just saw the headers are going to be authorization. So let's grab that, put it in here. And then we're going to do back six, we can write code in here, because we're going to use our API token. So dollar curly braces is how you put in code. And I'm just going to pass through this API key. So that's all I am doing. Next, what else we need, we need to pass through the content type. So content type, and that is going to be once again, I'm just going to paste it because I'm lazy, application, Jason. So that is how you would read what you are seeing here in order to create your own API core in your code. We're also going to have to pass through some more information. So essentially, what model we want to use and the message we want to send over. So I can just copy this, essentially, maybe let's do that. And let's do a comma here and do body. And then whoops, we don't need to these body, and then just paste it like so. So great, we have the model where you're going to use GPT 3.5 turbo, still awaiting GPT for access to it, we're going to have the messages. In fact, we don't need these, we can actually get rid of that. Just like that. Same for that. Same for the role. And same for the content. The content, though, we can pass through the string of hello, or we can pass whatever we put in our input. So we will do that. And we can also put the maximum number of token words the bot should return if we want. Or we don't have to. So you can put max token if you wish. But I think let's just leave it. Actually, maybe let's do it just so you know how to do it if you want to limit the tokens. So max tokens. I'm going to go with 100. Okay. And I think we just need to pass this through JSON string of five just to make sure it's JSON. So I'm going to pass through that whole object like so. Wonderful. So that is looking good. Okay, so we're making the API call pass through the option. So all the information it needs, which is all of this. Now let's get the data. So we're going to use await, I'm going to await the responses JSON. So just like so. And then once we have that, let's save it as the const data. Okay, so essentially, that's doing the fetch. And then we're waiting for the response. So let's say this under response. And then when we get the response, we're going to get the JSON from it. But oh, this is actually an async method, which you might not know, but it is, which is why we need to await it again. And once we have it, we can save it under data. And once we have data, I'm just going to console logout data for great. And now let's catch any errors. I'm just going to pass through error. And I'm just going to console error the error. Okay, let's test it out. Well, we can just do Hello. So that just means that let's refresh. If I click on this, it will make the call and we're just waiting for it. And amazing, we just pass you Hello. And then this whole object comes back, we're going to go into the object, get the choices, go into the first item in the array, and get the message. So the message is, Hello there, how may I assist you? So that's essentially what we want to show in the in the browser, right? So instead of just console logging out the data, what I'm going to do is pick out the output element. So this p right here by its ID. So let's look in the whole document again, document, query selector, this I'm going to look for the ID of output. Let's save it as output element. So I'm just going to get the output element. And I'm going to use text content to get the data, however, go into the object, get the choices, as I said, go into the first item of that array, get the message. So let's have a look here again. So we're getting this as data, right? That's what we saved as data, we then go into choices, get the first item of the array as that as an array. So go zero, and get the message dot content. So we're just going to get that first item back each time. So great, let's check it out, I'm going to try once more. So obviously, this is just sending the string Hello. And then we should see Hello there, how may assist you today. So this is looking good. Of course, we want to send our own messages, not just Hello, right? So let's carry on. One thing I also want to do is just save it as the history. So if this exists, right, because we don't want to save empty strings, we just want to make sure that if something exists, then what I'm going to do is create a P element, document, create element, and I'm going to create a P element, so a paragraph element, or maybe let's make it now let's make a P element that is fine. And that P element, I'm going to get the text content. And I'm just going to get whatever we actually wrote in the input. So actually, maybe we should do the input first, I'm just going to comment this out for now, I'm going to pick out this input. So document, query selector, input, we only have one, so it's fine for me just to pick out the whole input. And let's save it as input element. And instead of passing through Hello, I'm going to get an input element value. So whatever value that input has will be passed through. And also, I also want to pass it through to history. So if a message comes back to us, and it's successful, I want to get the input elements value, and just essentially add that text to the P element we just created. We're at the moment, this P elements just floating around, we can't see it, I need to append it to the history element. So let's pick out the element by the class of history. Document, query selector, class of history. So dot is class. And let's say this as history element. And I'm going to get the history element. And I'm going to use a method called append to put in that P element. Once again, if text comes back to us from the API, then we create a P element, we add some text to it, which is essentially whatever we put in the input. And then we get it and we put it into the history element. So that's all I have done for now. So if we have a look at this, let's put in something, what can I ask it? What day is it? Question mark and send this we wait. Okay, it does not have, I would have thought it would tell me what day it is, but it has not. And we get that in the history. Okay, so if we look in here, the history, the div with a class of history, which before had nothing in it, now has a P element with the text that we wrote in here, right? So that is pretty cool. And if we of course add more, that will be appended to that as well. So this is all looking wonderful. So far, we have done a lot with we have a few more things to do. If I click on this, I want to bring back the prompt. And if I click on here, I want to clear this input. So let's do that next. Let's pick out the button. So document, query selector, button, there's only one, so this should be fine. What should we call this, I think we should just call it button element as there is only one in this project. So I'm going to grab the button element, let's just do so down here. And I'm going to add event listener. And if I click on it, I want to clear the input. So let's write a function called clear input. Let's do so maybe up here, function, clear input. And I'm just going to grab the input element, get its value, and just override it with an empty string. So that should now work. One last thing I'm going to do is also add an event listener. So if we click on anything in here, it brings it essentially gets that text and puts it back in here. So let's do it. I think as soon as we create the p element, right, and we put in the text, I'm also gonna add an event listener to it that says if we click on it, all I want to do, I'm going to make this a callback. So just we can we so that we can essentially pass stuff through into a function that I'm going to call change input. So into here, I am well, let's actually maybe just pass through the p elements text content, as that's what we're going to want to change it to. And let's define our function. So let's define up here function change input. And then we're going to pass through a value that value is essentially what we want to change the input to. And what I'm going to do is use document query selector to look for the element of input again, so whatever the freshest value of it is. So I'm just going to save it as input element for now and get that input element value and just assign it the value. So there we go. I think we have done it. I think we built our own ChatGPT clone, let's give it a go. So let's ask it something else. How are you today? Send and wait for that to come back. Okay, so there we go, we are getting some text to come back to us, and it gets saved up here. And then if I go, what can I ask it now? What is four plus two and send that over. The answer is six. And then if I click on here, that will get back the same question. So I don't have to type it out again. As you will see that's updating. And if I click on here, that will or should clear the input. Why is that not working? Let's inspect here. Let's have a look in here. We've missed the value. While we're here, I'm just going to change the OPC or the input to be much more like the actual thing. And I should also check that the input value exists. And if the input value exists, and the message that comes back exists, then I only wanted to put it in the chat history. So there we go. Let's try that again. Let's refresh. What is six plus two? And that should give me the response. How are you question mark? And that should ask it the question. And then I can bring back the previous input as well as clear this so we can start again. Great. So I hope you've learned something new. I hope you've learned how to use the ChatGPT API or otherwise the OpenAI API that powers ChatGPT. As a beginner, it could be quite frustrating when you want to use this, but you haven't learned react yet. So that's how you would do it for your own personal projects. If you want to level up, check out my video on how we build the same thing, but in reacts next. Hey, everyone, and welcome to this video, which we're going to learn how to use the OpenAI API, or in other words, the thing that powers ChatGPT to build our own ChatGPT clone. And we're going to be doing this in react for the front end with a Node.js backend. So that's what we're going to be doing today. The final product will look like this, and it will allow us to write text prompts. And once we do that, we'll start a new chat automatically. And then we can carry on having a chat with the AI. Now, if we want to create a new chat, all we do is click on the button, and that will generate a new chat for us. And automatically, the first text prompt will be saved to the history. And the best part about it is that we can go back to the previous chat and add to again, go to the next one out of that, and that will be tracked accordingly. And of course, we can create new chats as well. So that is a cool feature that I'm going to show you how to do. And we're going to be saving that to six. Of course, we will also be keeping our API keys safe. And we're going to try to do it with not using all our free tokens. Okay, so I am super excited about this. What are we waiting for? Let's get to it. Okay, so first off, I'm just going to create a new project, I'm using WebStorm. So all I have to do is click here, and I can select react. And then I can call this whatever I want. So I'm going to call this react chat, gbt, G, okay, and that will get made in my WebStorm projects. And it's going to use this command, so NPX, and then the string create react app as one. So that is separated by a space here. And I'm just going to click Create. Now, for those of you who aren't using WebStorm, all you would do is use your terminal. So here is my terminal, I'm just going to make it bigger. And then you can gravitate wherever you want. So I'm going to go into WebStorm projects, and then you would use NPX, create react app, and then whatever you want to call your project. So react chat, gbt, clone, and hit enter. Okay, so that is what you do. Of course, I'm not going to do it this way, because I'm using WebStorm, which has done all that for me. So this is essentially spinning up all the files and configuration I need for this project. So we're just going to wait for that to do its thing. So when that is ready, it should say happy hacking. And there we go, happy hacking, as I will see all the folders and correct files are already in there for me. So let's just clean this up a little bit. We're not going to write any tests. So I'm just going to delete these two. I'm going to delete that. We also don't need a logo. So let's go ahead and delete the logo. I'm also going to delete the app test files, we're not writing any tests, as well as the CSS file, because I'm just gonna pull my CSS in one file because it's a small project. So that's it. So at the moment, you should just have these three files in the source directory, the app.js file looks like this, and I'm just going to delete everything in here, so that we can start fresh, that is what it should look like. I'm also going to change this to a functional expression, just because that is my preference. And we don't need these two inputs. So this is what your app.js file should look like. Your CSS file should just be empty. So we can start fresh. And your index.js, well, we're not writing any tests. So let's delete that. You don't need this. And delete the semi colons. Again, that is a personal preference. And we are ready to roll. So that is my index.js file. That's my index CSS file. And that's my app.js file. And that's all that we should have in here. Great. So again, like I said, this is a really small project. So we're actually not going to have any components or anything like that, because this is about learning how to use the OpenAI API. So I'm just going to start building up my app. So I'm going to set up by having two sections. So one section, that's going to be for the sidebar, and one section is going to be for the, I guess, main part of the app. So let's give this the class name of sidebar. And this the class name of main so we can differentiate between the two main. So what do we want to go in our sidebar? Well, I want to have a button. This is going to create a new chat. And I'm going to just put a little plus text icon here. If you want to know where I got the text icon from, I'm just going to search for it, you can simply just get it by searching for it. So if you visit this URL, you'll be able to get that plus sign as well. So I believe so. Anyway, let's just find. Yeah, so there it is. Great. So that is my text icon. Next up after the button, I'm going to actually have an ordered list. And this is going to be for the history of all our previous prompts. So I'm just going to pick it out by the class name of history as well, just to kind of make things more readable. And in here, we're actually going to map out onto list items, the first prompt that we wrote for the chat, the first text prompt. So we'll leave that for now. And lastly, I'm going to have a nav element. And in here, I'm just going to have the p element of made by Anya. So that is my whole section, my first section, it's got three children, which I want to space out evenly. So I'm going to use justify content space between to space them out evenly. So shall we do that? Yeah, let's do it. Okay, so let's get my index CSS file up, I'm going to say that everything so star means everything, everything in this, I guess project is going to have the font color of white and the font family of open sans. So open sans is something that I'm going to get from Google fonts. So please go ahead and just get it as well. So just go to Google fonts. And then all you're going to do is search for open sans. There it is. And then I'm going to select the appropriate ones, I'm going to actually select all the weights, so that we have all of them to our disposal. So I think that's it, I'm not getting the italic ones. So if you click here, we can then import them, you can do import them into the HTML or the CSS, I'm going to import them into the CSS, I'm going to grab that. And I'm just what I'm going to do is just paste it making sure that the semicons at the end, and you can see all the font weights that we have to ask disposal. So now if I want to use this, use the rule that I need to use, we can have anything as a backup, I'm happy having sans serve as a backup as they have kind of given us. So there we go. So yeah, everything in here is going to have essentially white text that is open sans and open sans doesn't work or revert to sans serve as the backup. Next, I'm going to grab the whole body and I'm just going to get rid of any default margin and padding. So margin and padding is set as zero to get rid of any weird funky white borders that we may have. And now let's make this bigger. I'm going to grab to the wrapping element. So the element with the class name of app. So let's grab it by the class name. And I'm just going to give the whole app a background color. So the background color I have picked out already directly from chat gvt. And it is this 343-541. Okay, I'm just going to make sure that the side bar. So let's style the sidebar, but also main. Let's give them both some styling first. So the sidebar, I want the background color of this to be darker. Again, I have picked this out as 202123. And I'm actually going to make sure that the height is 100 of the viewport height, but the width is only 244 pixels, and it's going to be stuck at 244 pixels. Okay, and while we're here, I'm also just going to make sure, well, let's just leave it at that for now. And the main, I'm also going to give it a height of 100 of the viewport height, but width, I'm just going to say 100%. So it's going to try to take up 100%. Obviously, we've got the sidebar there. At the moment, though, let's go ahead and start this project. So in WebStorm, I can just hit here and it will run the command npm start. So essentially look in here and run this command. But if you are not using WebStorm, I'm just going to show you how to do it. You would find the project first. So WebStorm projects, and this is what we call this React, try to be clear, you would do npm run start and hit enter. Okay, because you're literally just doing npm run and whatever we've called this, we call this start so that it runs this. So let's go ahead and do that on WebStorm. So I'm just going to go here and it should start up. So great. This is looking very cool. I'm just going to inspect it for now. So I want essentially this to be, you know, just spaced out evenly, right, I want it to appear this to be at the bottom, and then history, which at the moment doesn't know how much starting to be in the middle and the new chat button to be at the top, I can use so with display flex. So let's minimize this minimize that too. And on the sidebar, I'm going to initialize flex box. So that was initialized so I can use it. And we now want everything to be stacked on top of each other. Because if I save this, it will, you know, stuck next to each other, we don't want that we want it to be over each other. So flex direction, column. And now I'm going to do justify content space between. So now they are spaced out. And if I kind of move this, they'll always be at the bottom, the space between all the three children should be equal. So in here, the three children, there's one child, there's the second child, and the third child has equal spacing between them. Let's carry on. Maybe let's just make this a little bit smaller. Okay, maybe let's style the button and the now fast before moving on, let's just complete the sidebar. So there is my sidebar. I'm also going to grab the button, and just give it a border solid 0.5 pixels. And then make it kind of well, I'm going to do white, but then I'm going to make it 0.5 opacity. So A is for opacity. Make sure to spot button correctly, we shouldn't really use RGB and hex. So we can swap that out at the end. And then let's also give it a background color of transparent. So we've given it a border, you know, background color is round off the edges, border radius. Let's go with five pixels, and then padding 10 pixels margin 10 pixels. Okay, so that's what I have done. So now it looks like that. Very much like the real thing. Now let's do the navbar. So let's go back here and let's grab the nav element. And all I'm going to do is give it border at the top. So I'm going to do border again, but this time just border top, and literally just copy this line really. Okay, but that's going to apply it just at the top and let's also give it the same padding. So let's just copy this just to keep it consistent. Okay, so now it looks like this. Wonderful. This is looking great. Now, if I was to start adding elements into here, so into the history, so say we have a list item, or doesn't really matter what we do from now, it's going to look like this, I don't really want the dots here. So I'm going to show you how to get rid of that, as well as get some padding to the whole unordered list. So let's grab the unordered list first. Okay, I'm just going to grab by the element, because we don't really have any other unordered lists in here, right? I mean, you couldn't grab it by the history, I gave up class name to make it more readable. So maybe let's just do that. So dot history, dot is for class name, as hopefully you know. And let's apply the same padding and margin for consistency. And also just gonna maybe give make sure that it spaces out 100%. And now every list item that lives inside the element with the class of history, I'm just going to use list style type none. Okay, and that will remove that dot. Okay, now I'm also going to pad it out. However, I just want to pad it out 15 pixels from the top and bottom and zero from the left and right. So that is a shorthand for doing that I would apply to the top and bottom of this to the left and right. And I'm also wanting to give a cursor of pointer, because I'm going to want to be able to click on these, right. So I want it to be very obvious that we can click on them by changing the pointer like so. Alright, done. So we're now done with the sidebar. Maybe let's get rid of, but let's keep that for now. Okay, so let's move on to the main section. Now let's do it. Now my main section, well, I'm just going to give us the h1 element of ania and gb2 like so. And then I'm also going to, I guess, make a feed. So we're going to use another unordered list. So luckily, we gave that a class name, because I am going to use another unordered list. So let's give this a class name of feed, because it's going to be for our feed. And we're going to also map out onto here some list items, which is essentially going to be each chat. Do we want to do this? Now, maybe let's leave that for now. So we're going to map on to, of course, you know, list items, but we'll leave that. Let's then make a div. And let's give this the class name of bottom section, and it's going to basically hold everything that needs to be on the bottom section. And what goes in a bottom section, well, we're going to have an input, but I'm going to wrap it in an input container. So I'm going to make a div with a class name of input container, so that we can essentially position a little icon on top of the input. So let's put an input. There we go. And then I'm also going to add a div and give this the ID of submit. Okay, so that is it. And again, I'm just going to use some text symbol. If you want to Google it, that is it. And you can get it from Unicode characters. So that is the URL to do it. Great. So now let's go back here. Okay, so we've got an input container. And under the input container, so make sure it's after this closing tag that's linked to here, I'm going to put a p element. Let's give this the class name of info as I want to style this up a little bit smaller than a normal p element. And it's just going to have the text I've stolen from the ChatGPT website. Okay, wonderful. So we've now finished with all of this at the moment, you know, it's under here, because we have our sidebar here, and then our main is under here, we need to use two to appear next to each other. So the parent of the sidebar and the main element is the div class name of app. So let's go back into here. And just right here, I'm going to use display flex. And that should make both of these appear next to each other like so. Great. Let's style up the main element a bit more next. So the main element, well, I want everything I guess, to kind of be in the center, but also with space between. So once again, I'm going to initialize flex box. So display flex. And once that is done, of course, everything will appear from left to right, we want it to appear from top to bottom. So what I can do is use flex a direction column. And now I'm just going to justify content space between. Okay, so it looks like that another center the text, as well as everything else, actually, so we're going to use align item center, which again is part of flex box, you can't use a line items center. And you can't use this. In fact, you can't use any of these three without initializing flex box. So just keep that in mind. And now let's also center the text. So once again, I'm going to do text aligns time center. And I believe that's all we need to do. So that is what it looks like. Next, I am just going to make this smaller and more transparent. So the p element with the class name of info. So what I'm going to do is grab the class name of info. And the color of this text is, well, it's not going to be white. Let's override that. So I'm going to do RGB a 255, 255, 255, 0.5. Okay, so T is what I'm going to give it. Next, I'm just going to send the font size, font size 11 pixels, and pad it out just a little bit though by 10 pixels. So at the moment, it will look like this, okay, just much more, I guess, realistic. Let's tackle the input next. So the input, well, of course, the input and the icon are children of the input container, and we want to do some positioning, which is why we're going to use position relative on this, and then position this based on the parent by giving it position absolute, and then some values for top and left, I believe. Let's have a look. Okay, so let's grab the input container, actually the other side. So top, right or bottom, right, top or bottom, it's up to us. So let's yes, grab the input container. And like I said, we need to give a position of relative relative to everything else. So essentially, not much will change for that. But we need to do it in order to position the child. And one other thing that the input container lives in is the bottom section, which we're going to have to assign a width to. So the bottom section, let's just say we want this to have a width of 100%, just like so. Oops, there we go. I'm also going to use display flex on it and make sure that everything stacks on top of each other. So I'm going to use flex direction column. And then let's also center everything. So justify content center and align items center. So everything's going to be centered from top to bottom and then left and right. So that should be good. So yes, it is. And now let's so here is the I'm just going to show you exactly how big that bottom section is it stretches. And then if we go into the bottom section, I need the input container to stretch to. So the input container. Let's also give it a width of 100%. But then also stop it so cap it if it gets to 650 pixels. Okay, great. So again, that won't look like much because now we need to stretch the input that lives inside of it. So now let's grab the actual input itself. And the width is going to be 100%. Now I'm also going to get rid of the border of this. Let's give it a background color, which is going to be RGB a it's going to be white, and it's going to be super opacity 0.05 I'm going to do. And let's also give it a padding at the top of 12 pixels and 15 pixels from the left and right. So this is applied to the top and bottom, and this to the left and right, and round it off. So I'm going to do border radius, five pixels. Okay, so one other thing that I should probably do is, well, let's have a look at what this looks like at the moment. And so actually, this looks good. I'm happy with that. I don't really want any focus on this. So that blue line. So what I'm also going to do is grab the input. Focus, I'm just gonna do outline now. Okay, so that will get rid of that. And one last thing, I'm just also going to add some box shadow, I'm essentially going to overlay lots of box shadows on top of each other. The first color is going to be black with 0.05 opacity, zero x axis, 54 pixels y axis, 55 pixels blur, and then overlay it with another one. So in fact, I'm just going to copy this, because I think we're going to keep the color the same, but just change the x and y and blurs. So we'll make this minus 12, and change this to 30. Do it again. And this time zero, let's put four pixels, and six pixels. And then again, zero, 12, three pixels, and a final one of zero, minus three, and five. So there we go. That's a lot. And we just need to change all of these to be commerce instead, because it's just one long box shadow. So the desired effect is now that let's position this next. So this time, what I'm going to do is grab the submit. Okay, so the deal with the ID of submit, and I'm going to use position absolute. So at the moment, that will appear here, but I wanted to appear here and wanted to position it from the parent from the bottom 15 and from the right zero. So let's go out and do that bottom 15 pixels and right zero. And I'm also going to change the cursor. So like we did before, to be pointed so that we know that we can click on this. And the end result is that you can probably move it a little bit down. That does seem kind of high up, or maybe let's make the font size bigger for here. Maybe let's do that. So again, on the input, I'm just going to change the font size to be 20 pixels if we write in the input. And great, that is so much better. I think we're now ready to actually cook this up a little bit to the API. And for this, we're going to go back. So let's do it. So back in here, what I'm going to do is on the same level as the package JSON, I'm just going to create a new file. So let's go ahead and add a new file, I'm going to call it index, or let's call it server j s, you can call it whatever you want, really. So that is now our server. So that's our back end. Okay, and we're gonna have to install a few things. So let's go ahead and do that first. So I'm going to install a package called cause Express. Know them on. And I think that's it. If you want a bit more information as to what these are, please do check out my full site developer course where I go into this in a bunch more detail. Okay, or you can do your own research, just research those packages. Otherwise, let's carry on. So you will see those packages happen as well here along with their version. So if something isn't working, make sure to revert back to these versions and install that version. Okay, if you are watching this in the future. So now that we've done that, let's write a script to start our back end, I'm going to call it start. But this time, I'm going to write back end. And let's differentiate it by writing front end for this one. Run and let's make that biggest you can meet it. And to start this, or we're literally going to use the package that we just installed to listen out for constant changes on my back end. So I'm going to do node of one. And then we're going to listen up changes on server j s. Great. So now let's start our front end again. So I'm just going to stop it from running here, and your NPM run, start front ends and hit enter. Okay, so that will just rerun that and I'm going to create another tab so I can run my back end. So keep both of those running NPM run, start back end and enter. So now our back end is running. So let's actually define a port, port to run on first, I'm going to minimize that. So we're done with the package JSON, let's get off our server j s file. So we're going to run our back end on port 8000. And let's also just go ahead and require those packages that we literally just installed. So we're going to use express, but also going to use core. So require course, to get rid of any calls and messages that we might come across. And now let's initialize it. So I'm going to essentially get express, we've got the package, we've saved and express, I'm going to release everything by doing that and save it on the app so we can use it in this project. So now I'm also I know I'm going to be working with JSON. So I'm just going to use up express JSON. Now allow us to work with JSON when we start sending stuff from the front end to the back end with our post requests. And I'm also going to do up use course because I know that I'm going to run into some course error messages. So that is the setup. Now I'm going to do app listen to listen out, essentially on port. So let's actually just write a message your server is running on ports, and then whatever the port is support 8000 is 8000 that we're using here. Okay, we actually need to make this a callback function, plus report as the first parameter, and this as the second parameter, and then console log this out to console log this whole thing. Great. So now if we look in here, it says your server is running on port 8000. And if I make any changes, so if I just do console log, hi, that will really run. Okay, and same if I visit localhost 8000 here. That is our port and it's running, of course, we haven't written in the express routes. So that is why it says cannot get anything when we visit the home route right here. But let's carry on. So I'm just going to minimize that. Okay, so now it's time for us to get our API key. So all I'm going to do is head over to OpenAI. And I'm going to go to developers API reference. Okay, of course, you have to be signed in. So just make sure you are I am currently signed in. And we are going to get our API key. So all you have to do is go here, view API keys. And I'm going to create a new secret key. So copy that it's really that easy. There it is. If you are got lost, just make sure to visit this URL when you are signed in. And you can create as many as you want. Of course, if yours gets taken, or you think it's compromised, you can delete it as well. So keep that in mind, I just created one. And all I'm going to do is essentially for now, I'm just going to put it here. Like so. So there we go. Right now it's in here, but we will be creating a dot uv file to keep it more safe. But you know, I just want to get the basics done first. And now let's write our route. So if we post to the route, let's say if we go to which we do local host 8000 forward slash completions, this could be whatever you want. Essentially, all I'm saying is that we visit forward slash completions, then we will get something back here. Okay. And then the syntax for this have a request and a response. So put those in parentheses, this is actually going to be an async function, because we're going to use the await keyword inside of here. But let's cross that when we get to it, we're going to do try and catch. So we're going to try something. And if it doesn't work, we're going to catch the errors. I'm just going to console error them out. So console error, error. Okay. Great. And what we're going to try, well, we're going to use the fetch keyword, make sure you are on the latest version of node in order to be able to use the fetch API keyword on the back end. So just keep that in mind as well. So all I'm going to do is use the fetch keyword, and we're going to fetch to the completions API. So once again, let's go back here, let's go to the documentation. And we're going to use the chat completions API from OpenAI. So the model we're going to use is I don't have access to GP chief GPT for yet. So I'm going to use GPT 3.5 turbo. So let's go here. And if you're going to chat, create chat completion, not completion, okay, chat completions, this is the URL that we're going to need. Okay, so I'm just going to make that smaller. Here we go. It's a post request to this URL. So I'm just going to grab that and paste it in like so. Next, we're going to have to pass through some options, like what kind of request is going to be so what methods some headers with our API key, as well as actually what model you want to use on the message we want to send over. So I'm going to define that here constant options. It's going to be a whole object. And like I said, it's going to take a method is going to be a post method, as we discussed. And next, we're going to pass through some headers. So the headers that it's going to take, well, we need to pass through some authorization. So make sure to spell this like so authorization. And the authorization is just going to be a string with our const. So that's what I put back to so we can use that code in here, you have to put bearer, and then that and then we're just going to put some curly braces so that we can pass through the API key. So that's how you'll put in variables, you'd use the dollar sign and the curly braces. Okay, next, we're also going to have to pass through the content type. So content type, and then we're going to put application JSON as we're going to be working with JSON. And now we can define the request body. So we're going to have to pass this through JSON stringify. Okay, and it's going to be an object that we're going to send through. And we're going to justify it Jasonify it thanks to Jason stringify. The model we're going to be working with, as I said, I don't have access to ChatGPT for but if you do, please go ahead and use that because the results will be better. I'm going to use this model right here. And the messages we're going to pass through are going to be so the role is going to be user and then content or the content for now, let's just put how are you okay, and we'll replace that we're just going to check this works. And I don't want to go over 20 tokens, I'm going to limit my tokens. So I can do max tokens 100. Okay, that will just mean basically every string text prompt is tokenized. If you want to check how many tokens your string is going to use, you can check it before using this on the OpenAI documentation. But I think just you know, put a max in here just so you don't go over usable free credits and whatever. So there we go. One thing that I will say is that we can't pass over Jason from the front end to the back end unless you have this right. So if you're having any issues when it comes to that, make sure you have this that's very important. Okay, great. So those are all my options that we're going to pass through with this URL. Like I said, this fetch API is an async method, which is why we're gonna have to await it. So we're literally going to wait for something to come back. And we're going to save it under response. And because we're using the await keyword in here, this whole function is an async function. Again, check out my full site developer course, if you want to learn more about this in more detail. So now once we get the response, we're going to wait for it. And then we get it back. I'm going to get it to Jason, but oh, Jason is another async method. So we're going to have to await this to we're going to wait it. And once we get it back, we're going to save it as data. Great. And let's just send this over to localhost 8004 slash completions by passing it through reset. So now let's check it out. So first off, after you've done this, let's hook this up to the front end, I'm going to do so with an on click. So on here, if we click this div, I want something to happen. And I just want to get message. Okay, that's all I'm going to do. In fact, maybe let's do messages as it could be plural. And let's define it up here. So right under here, we're going to define get messages. So const get messages, it's going to be an async function, because we're going to use the fetch keyword in here too. And once again, we're going to use try and catch so try. And we're going to catch any errors. And what are we going to do this time? Well, first off, we're just going to console error any errors. And in here, once again, we're going to use the fetch keywords that await fetch, we're going to pass in the URL this time that we're going to get it from our back end. So right here, that's what we're going to get it from. So paste that in like so. And again, we're going to have some options because we're going to have to pass through the some data, right? So exactly what we're writing into the input. So let's define our options again. Again, the method is going to be a host method. The body this time is, I'm just going to actually pass through a message. And it's going to have a value. But at the moment, well, yeah, we can we can pass it through, let's just put, hello, how are you so hard coding it. And we're gonna have to wrap this through JSON stringify again, so JSON stringify. And we're going to get that whole object and pass it through. Okay, great. And I'm just going to add headers as we are working with JSON. So I'm going to put content type application. Jason. Okay, wonderful. So once again, we're going to wait for the response. And once we get the response, we're going to get its JSON. And let's save it as data, just like so. And then for now, I'm just going to console log the data. So let's test it out. So at the moment, we're just hard coding. Hello, you that will be passed on to the server, but we're not doing much with it, because we're just going to send how I do from here anyway. So let's just try this out. So here, if I click on here, I don't need to put anything in. We're just going to wait. The promise is pending. Why is that? That's because we didn't wait to wait for that to come back. That's why we got a promise there. Let's try again. And great. So we get back this whole object. Okay, everything is working. And if we look in the object, and we look under choices, and we look under the first item in the array, we get a message from the assistant saying I'm an AI language model. So I don't have feelings like humans do, but I'm functioning properly and ready to assist. So we're getting back that message. Next thing we want to do is actually show that message in here. Instead of hard coding, how are you, we want to actually get the input, right? So let's do it. Well, first off, I'm just going to save that response. So the whole message to state and for that we need use state from react. So I'm going to import use state and I will add it use effect as I know I will need that from react. So now if I want to save that message, I can go const message, set message, use state and it's sort of with the game now. And so now at the moment, we get now go, we assign that the value of null to message. And if you want to say change, sorry, the value of message, we use set message to do it. So I do want to change the value. So I'm just going to use set message. And what I'm going to do is go into the data, get the choices. So just like we did before, go into that array, get the first item and get the message. Right? So once again, here's my whole object. So that's technically data, you go into choices, get the first item of that array. So zero, right, zero, and then we get the message. So the message will actually be an object that has the content and the role. Okay, I want to save both. So let's carry on. So we don't need to console log this out anymore, the message with the role and the content is being saved under the constant message. So it's not a string, it's an object. Okay, so what do we say we want to do next, right, we want to hook up the input. So let's save the value of up here to value, set value, use state, null, and we're going to override the value if we interact with the input. So let's find that input, here we go. We're going to display the value. So whatever the value is right now, we're just going to assign to the input at the moment, it's no, of course, but on change of this input. Well, I'm just gonna pass through the event. I'm going to set a value to wherever e target value is of that input. Right. So now up here, if I console log value, just anywhere just above the return. And I type something to get up our console log. See, that's what technically console logging value or console longer app line 27. And it will change. So that is how we are changing the value constant. Okay, and next, let's actually whatever state it's at, I want to send it over. So currently, I would send over this, let's hook that up. So what I would do, this is super simple, all I would do is get rid of the string and put the value instead. Okay, and now to pass it to our back end where we're passing it through with the body, we need this to be here in order for this to work. So don't forget that. And that just means that instead of having this here, I can get the request body message and pass that through like so and that will now be sent over to OpenAI. Okay. So again, if this doesn't make sense, check out my full site. So that of course, I don't want to keep banging on about it. But you know, there's a lot of stuff we're doing here that from beginner will be way too much. So do check it out. So now the one last thing I'm going to do, well, I'm just going to console log the message that we get back. So that saved on the message and try it out. So let's do what is two plus two, send that and great, we get four and it's from the assistant from the AI assistant. So let's now use this in order to create a chat response, okay, as a list item. So let's do it. So let's go back in here. And what I'm going to do is actually save all the previous chats. And you set previous chats in order to change that. And I'm going to start off with this being an empty array this time. Okay, so that's what I'm going to do. And I'm going to actually get this whole message. So whatever's coming back here right now, because back with the role and content, and I'm also just going to assign a title so that I can essentially say that, okay, this chat has this title, I'm going to lump it together. How is this chat is a new chat, I'm going to give it a new title. And it's just going to be the current the first prompt that we give our chat. So let's do it. Let's do this maybe in a use effect. Okay, so just like so. And I'm going to say that anytime the message changes, so whatever we get back from the open API, I want this to run. I'm also going to save the current title. So current title, set current title, use state, and start off as being an empty array as well. So I'm also actually going to change this if the current title changes. So whatever the prompt for the chat, whatever the start of the chat changes, then we run this again. So let's just console log the current title, the value, so the input value and the message that comes back to us. Okay, just so we can see a little bit more of what is going on. Great, that needs a comment. So what do I want to do? Well, if there's currently no current title, right? So if there's no new title, we don't have a chat. However, we do have a value in our input. And we do have a message that has come back to us, where then I want to set the current title to be whatever the value is. Right? So hopefully that makes sense. And once we save it, we can add it to the history. However, if there is a current title already that exists, and the value exists in an input, and we get the message back. So we're on the chat currently, we're still chatting away, we just want to set previous chats, and we're going to essentially get whatever's in that array already, right? And this is how you would update an array using use state. I would open up the array, I would get the previous chats and spill them out. But then I'd also add, I'm going to add an object, I'm actually going to add two objects. So just like so, maybe I'll put this on a new row, so it's more readable for you. There's one object. And here is a another object is going to have the title. And the title is going to be the current title. So whatever the first prompt was, the role is going to be the user. So essentially us and the content is going to be the value. So I'm using kind of what OpenAI gave me in terms of structure for the object, but I've added my own title, so we can save it to state. And then I'm literally just going to get what chat should be gave back to me. So roll will go into the message and get the role. And I'm going to get the content and get the message content. Okay, and I'm also just going to give this the title of the current title. So let's just talk this through. So every time we are saving previous chat, so a new chat, I'm saving whatever we asked the AI, and we're signing the role as asked the user. And I'm just going to save the current title to make sure that all the chats are lumped by the first prompt. And I'm also setting over the other object, which is the response from the AI, which we've saved under the const message, right? That was an object that had a role and content. And I'm literally just getting the role from that object and getting content from that object and assigning it to role and content for my previous chat state. I'm going to show you what this looks like. Okay, so there we go, we have a few more things to do. And that is actually set the history by the current titles. So let's go ahead and do that here. So here's my section of main. And actually, let's just show this if there's current if there's no current title, then we show this however, if there's a current title, then we get rid of that. And here we're going to map out onto list items. However, maybe let's just see what this looks like at the moment, I'm just going to console log out previous chats. Okay. So that's what we're going to do. So let's go back here. I'm just going to let's start a new chat. What is five plus five? Ask it. Okay, so that is essentially these are my previous chats, we've created an object that has the content of what we asked as the user. There we go. The title is an empty array that is strange, we need to essentially change that current title. And then our second object, the content is 10. Because that's the answer that we got back from the AI and the role of the AI is the system. So why is title saving as an empty array? That is because the current title, we did set this to be an empty array, this should actually be null, because we're just going to save a text prompt. And where do we set the current title? Well, essentially, this should have done it for me, because we're listening out for current title changes. And if there is no current title, which technique that is not, okay, because before is an array that didn't run, let's try that again. So what is five plus five? Click on that. Okay, and great. Now our title gets populated with the prompt itself. And both of them have that prompt, right? And now because current title exists, we will miss this because current title does exist. And we'll just keep adding to the chat. Right? So let's ask another question. Are you sure? Okay, now there's four, because I asked it a another question. So there's me asking, are you sure as the user, the title is still the same, the first initial prompt, and then we're getting the response, okay, from the assistant. So great. So this is good. However, what if I want to change it, I want a new chat. So if I click here, I essentially want to clear this title. So let's do it. So I'm going to make a handle click function that I'm going to attach, or maybe let's call it something else. So on the button on click, I'm going to create new chat. So let's define it. So up here, const create new chat. I'm going to set message, I'm just going to clear everything, set message. So whatever the message is from the AI, I'm going to set that to null, I'm going to set the value of the input to an empty string. So we're clearing that. And I'm going to set the current title to be null two. So I'm essentially completely clearing it so we can start fresh. Okay, so shall we have a go at this? Let's try it out. What is one plus one? Let's send that over. Okay, so we get that there. The title is assigned. But if I start a new chat, and go, how are you and send that over. Okay, the title has changed. So great. So now if we ask more questions, the title of that should be still attached to. How are you? And it is so great. Now I'm going to get the unique title. So we're going to get everything and we're going to filter by the unique title and show it in the history as well as show the chat up here. So all I'm going to do is get the previous chats and I'm going to use filter. And I'm going to look at each previous chat individual, you can call this whatever you want. It's essentially every item in my array. And I'm going to literally just look at the previous chat objects title. And if it equals the current title that we are currently on, well, then we know that we're on the current chat. So let's save these filtered items as current chat objects, any object that has the title that is the same will be lumped into current chats. And this just means that I can then get current chats with the feed. Okay, and map out each, let's call it maybe a chat message, we're gonna have to use an index as we are mapping. So let's put that index here like so. And then I'm just going to map onto a list item. We of course need to give it a key. So I'm just going to use the index for that for this demo. And then I'm just going to essentially turn this key correctly. Put that there, put in two things into my list item element, I'm going to put in two p tags. This one's going to show you who sent the message. So roll is the user or the area assistant. And here, I'm just going to show the content of that message. I'm going to go chat message, message, great. And let's just give this the class name of roll. So it's really obvious. Okay, and we can pick it out later. So this is looking good to me, let's just check that that current chat exists fast before mapping anything onto here. And while we are here, I'm also just going to get all the unique titles, I'm going to filter, I'm going to get all the messages and just get the unique titles. Because as we saw, there's some titles that have like numerous, right, we just want essentially to filter them all out and just gonna return this title and this title and put them in an array for us. So I'm going to show you the code to do that. Well, this time, I'm actually going to get the previous chat, I'm going to map. I'm going to get the previous chat individual. And we're just going to get the previous chat title. And now I can pass it through. So all of this, I'm going to pass that through into a new set and make an array from it. So array from just like so and this will give me the unique title. So that piece of code is super useful if you want to get unique items from an object. So if I console log this out now, unique titles on line 61. You will see I've just got those unique titles and put them in an array, great, because now we're gonna map them on into the history. So let's get those unique titles. And instead of having blur, I'm going to get the unique titles. And if they exist, I'm going to map each unique title. Let's also maybe get the index. So put that in parentheses like so. I'm just going to get that unique title and pass it through here as code like so. So wonderful. I believe that should be it, we just need to give this a key. And it should now look like this. So it doesn't look great at the moment, we still need to style stuff up. But now, let's actually maybe add an on click so that if we select a chat, then we essentially pass through that chat that we click on as the current title, right? Because we want to change the current title to the other chat. So I'm going to define a function for this const handle click. And if we click on any one of those, so handle click is assigned to the list item in history. So in here, so we'll do it on here on click, we're going to call the function handle click. And we just want to click on it. So if we click on the first unique title, I'm just going to pass through the unique title that we clicked on. So now we need to make this a callback function as we just call that again. So we're going to pass it through into here that unique title. And we're just going to set current title to be whatever title we clicked on. Right? So hopefully that makes sense. It will do in a bit. So that's what we're going to do. And we're also just going to set message to null and set value to null. Okay, so we're just starting fresh. Great. So let's just test it out. What is four plus four send. So that should now get assigned to here. Great. And we can click on it. And my why is my content not showing up? Let's have a look. Let's go down here. Our chat message message should be content, right? Because that's what we saved it as here role and content. And that's what we're mapping out. So now if we look in here, there we go user what is four plus four assistance is eight. And obviously press it twice because I'm getting it twice. So let's just try again. What is four plus four? Send. Great. Are you sure question mark? Okay, and that's my assistance answer. And then I'm just going to start a new chat. And this time, how are you? Okay, so that's my question. And that's the assistance answer. But if I want to swap back and carry on this conversation, you are great. Then I can and it will be assigned to here, it does not get added to here. So great. This is looking so good. And if I clear it, we just get on your GPT. This is wonderful. A few more styling things that just style up these messages next. So all I'm going to do is style up essentially this list item here. So let's do it. So down here, I'm going to first style up the feed, I'm just going to give it a scroll. So I'm going to go over for scroll so we can scroll through the messages if we get loads, I'm going to make sure that the width is 100%. And I'm also going to just give it a padding of zero. So it's really squashed up to the edges. Next, any list item that lives inside my feed. So just like that, I'm going to use display flex, I'm initializing flex box. So they appear next to each other rather than stacked. And the background color, I'm just going to go with 444654. The width I want it to be 100%. And I'm going to give it some padding of 20 pixels. And I'm going to space out each list item top and bottom my 20 pixels and zero from the left and right. Okay, so at the moment, it looks like this, this is looking good. Let's just assign the line the text a little bit better. So again, I'm just going to say that any p element that is inside of my feed is going to have the color of our GPA. So a bit more transparent, I'm going to go with white 0.8 opacity, when you get the font size of 14 pixels, and I'm going to text a line left. And if that p element also happens to have the class of roll, I'm just going to assign it a min width of 100 pixels. So there we go. This is looking so good. Right now, you can of course add images in here instead of just use an assistant like the actual app does. But I think this is looking fantastic. There are a few things you can do to clear this up. For example, I do use RGB and hex colors in here. So please go ahead and change that. But overall, now you know how to use the OpenAI API. And you know how to make this cool chat, GVZ clone that has a history that you can kind of move back and forth to and add to the history and create new chats with as well. Finally, we're just going to hide this, I'm just going to stop this from running and import a package called.env. So just like that. And we're just going to create a new file. So new file on the same level as the server JS. So E and V, just like that. And we're going to define our API key. So instead of having it here, I'm just going to take it, you don't have to put it as a string that is implied, just paste it in. And now that means that I can just use process ENV API key. And of course, we need to require that package. So require.env config, and just start this up again. Okay, so just do that. That should now be picked up from this.env file. Okay, so you don't upload this.env file onto GitHub. Great. So great, I hope you have a fun, please take this to the next level, you know, add new features, it's yours. Okay, so we have learned a lot, but I'm really excited about showing you this section. Because in this section, we're going to use OpenAI's DALL-E model to generate images for us based on text prompts, as well as create variations of images if we choose to upload an image and so much more. So with this image API, we can create images from scratch based on some text we provide, as mentioned, we can also create edits of an existing image based on some text we provide. And we can, of course, create variations of an existing image that we upload as well, as mentioned in the intro. So let's check it out. So once again, let's get our endpoint, we will start off using this endpoint right here, we will pass through our API key. And this time, we don't need a model, what we provide, however, that is required is a text prompt that is a string, this text prompt is passed through with the request body along with some optional things. However, this time, these optional things vary. So we can pass through n, and this will represent the number of images to generate. And this takes an integer, and we can do anything from one to 10. So we can essentially get 10 images back if we want. We can also pass through the size. And this will generate a specific size of image. And we have three options to our disposal. So three squares, 256, 512, or 1024 multiplied by itself, we can even have a response format, which will specify how our image is returned with the URL being default, if nothing is put in, as well as the user to identify our end user if we need. So let's run it. Okay, so let's do it. As always, here's my file structure, I've got an index HTML file that is linking my app.js file. And there's nothing in here at the moment, we are going to be making a request to the image generations endpoint. Okay, so that's what we've been talking about, we're going to be generating images from prompts. And to do that, we are going to have to, well, get the fetch keyword and pass through that input here along with the options. And first off, though, let's do this in a function that's going to be an async function. So I'm going to call it async function, fetch images, that's what it's going to be doing. So now let's also define our API key up here. So we can communicate with open AI, and I'm just going to paste that there's a string, I'm just going to move that in here. Now, the endpoint that we're going to be using is this one right here. So make sure yours looks the same and the options, well, the method is going to be a post method, the headers are going to hold our API key. So we're going to use authorization, right, station, and then we're going to pass through bearer, okay, so capital B, and then I'm going to just put some code in here. So we're just going to do API key like so make sure that those are backticks. Great. Now we're going to have the content type. And the content type, well, it's going to be application Jason as we are working with Jason. So just make sure to put that there. Next in the body is what we actually want to send to the API. And we're going to pass through a object, right? And the object is going to take a prompt as we saw that is required. I'm going to go with a hamburger singing in the rain, you can put whatever you want. We do have to wrap this in Jason stringify. So let's just put the whole object in here. Okay, so make sure you're grabbing the whole object and just pasting it in like so. So the prompt is required, we can also specify how many we want, I'm going to say I want two images and the size, this is going to be from the sizes that we saw. So there's a few options, right, as we saw from the previous slide, 1024 by 1024 was one of them. Great. So now let's await this, let's save this response, just like so. And now I'm going to get the response and get it Jason. And once we get that, we're going to wait for that to come back to us, and we're going to get the data. So now let's console of the data, I'm just going to do console log data. And now let's call this. So this gets called immediately when we open the page. So I'm just going to open this up in the browser. And let's inspect to see what has come back to us. So let's just inspect this page. And today we get an object, we get an array of two images. So now if I grab this URL right here, I'm just going to grab that whole thing, let's go ahead and make that a little bit bigger, maybe. So just copy it, and make sure not to have the quotation marks at the beginning and end, because we need this to be a URL. Tada, we get a hamburger singing in the rain. And we get two of them. Now, great for those of you who just want the hamburgers quickly, however, I'm just going to show you how to do this with a car command as always. So here's my car command, as you will see, that is the endpoints that we are going to, we're just going to have to put in a prompt. So once again, let's put hamburger singing in the rain. And then let's put in our API key. So once again, just as always, just make sure to get rid of that, including the dollar sign, and just hit enter, and wait for that one image to come back, we pass you one n right here and the size of the image here too. So we should get back one image of a hamburger singing in the rain. And there we go. So let's grab that URL, paste it in here like so. And another hamburger singing in the rain. Wonderful. Let's move on. Now, using the DALL-E model, we can also do image variation. The image variation endpoint looks like this. And it will allow us to get an existing image and get up to 10 variations of it. Here are what we can pass through with the body. As you can see, an existing image is required. And all the others are optional and will default to a value if nothing is provided. I'm not going to be showing you how to do that here, because we're going to be doing this in a project as it is a lot more involved and will involve us having to have existing images in our projects. So we'll do that when the time comes. Another thing we can do with the DALL-E model is make image edits. This would involve using this endpoint right here. We are not going to be doing this in this course. But I did want to just flag this as something you can do. It would involve using an existing image, a potential mask. So another image you want to place on top of it, along with a text prompt to tell the OpenAI what you want to do with these images to edit them. Okay, so that is just something you need to know exists. And if you're ready to learn how to use the image generation and image variation endpoints, we're going to be using them in two projects coming up next. Hey, everyone, and welcome to this video in which I'm going to show you how to use the DALL-E model from the OpenAI API. So essentially, what we're going to be doing is building an image generator kind of like DALL-E, that's going to take a text prompt. And then it's going to generate four images for us based on that text prompt. So super basic, super simple, we're going to be building this in JavaScript, HTML and CSS. So essentially, this is a beginner video for those wanting to learn how to build their own things using the OpenAI API that powers tools such as DALL-E. So what are we waiting for? Of course, this is a front end project. So please don't go and publish this code with the API key that we will be using onto GitHub or share or anything like that. Because if you do, so I'm going to take your API key and steal all your credits. Or you know, if you have a credit card attached, they could potentially rack up loads and loads on your credit card bill. So please keep that API key safe. This is just for demo purposes. If you want to learn how to build out a more secure project, we will be doing that in another video where I build a front end and a back end to keep our API key safe. So let's do it. Please do have the fundamentals of JavaScript down. But if you don't, please do carry along anyway, and just fill in your gaps of knowledge later on after you finish this video. Okay, so let's do it. We're going to build this cool AI generator in JavaScript, HTML and CSS. So this is what it's going to look like. And then we can write a prompt and generate four images from it. And it's going to have this cool background too. So I'm going to show you how to do that as well. So first off, let's just start a new project I'm using WebStorm. So I'm simply going to click here. And let's call this JavaScript AI image generator, just like so and create. So that is created a directory for me in a directory called the WebStorm projects. And now I could just create a new file, I'm going to call it index HTML. And then I'm just going to create another file and app.js file. And now I'm just going to create a final file, it's going to be styles CSS, just like so. So there we go. There's our three files all in the same folder. And now let's link them up. So here's some boilerplate code for you. I'm just going to go ahead and call this AI image, generate door just like so. Okay. And now in the body, well, that's where all my code is going to go. But I'm also going to link up the app.js file, thanks for script type, it's gonna be at the bottom. So after all our other elements get read, then we go to the script tag. And I'm just going to link up the app.js file that's going to read our JavaScript. So the script is going to read our JavaScript from this file. Next, let's also link up the style sheet. So I'm going to use the link tag for this. It's a self closing tag, we'll do rel style sheet. And as the href, we're also going to put the path to our styles CSS file, which is just that as we don't need to go any folders or anything like that. It's in the same location as this index HTML file. So great, that is looking good. Now the background, I'm just going to show people how to do this, as a lot of people are probably curious. I'm just going to go to up high key dot app. So that's all I'm doing. And now we can generate our own way, which is pretty cool. So I chose a layered wave. And then all I did was kind of, you know, play around with this, or you can just choose your own like that. Or you can change the balance, the wave count, the complexity, which will be like, the contrast, the overlap, and just so much more, there's so much to do. And then you just download the SVG. And once that is done, you can open it up. And then you inspect the page like so. And then I'm just going to copy the whole element. Okay, so that SVG right there. So that's all I have done. Okay. And now if we go back here, I'm just going to in the body, paste it. So it is very long. And that's what it looks like. Let's just open this up in our browser. So I can go ahead and click here if I want if I am using WebStorm. Or if you are not, you can just copy the path, copy the absolute path, and then paste it in like so. So both things are okay to do. Great, now let's get rid of the little like border around it and make the stretch, right? So let's do it. So actually on here, what I am going to do is the width and the height. I'm just going to go with using the width and height from here. And then as the width here, I'm just going to go 100 viewport width. And then there's going to be 100 viewport height, we could have picked this out and done in the CSS file. So that is totally fine too. And on here, I'm going to grab the body and just get rid of any default padding and margin just like so. So then it should look like that. So that is much better now. So there we go. That's how you would use it. So that is how I like it at the moment. I'm actually just going to take the one I previously generated because I think I prefer it. But that is how you will get your one once you're happy with it once you played around with it. I don't play around with this one that much. And I just thought the other one cooler. So I'm just going to replace mine with the previous one that I made. Okay. And great, like I said, it's super long. So yeah, I mean, not much difference. Well, I just think likes that looks better. Okay. And now as the background, I'm just going to make it the same color as this last color right here. So let's find out what that is. In fact, I'm just going to inspect this. So the color for this is that. And now I'm just going to assign that to the body as well, just so that in case, you know, someone kind of zooms out like I did, then it just looks much better. I prefer that a lot more. Okay, let's carry on. So what is the next thing that we're going to do, we're going to add some elements in here. So just going to make sure I format that correctly. I'm going to next add a header. And that header, well, I'm just going to put the h1 element of any AI image generator, of course, you can replace this with whatever title you would like. And then after the header, I'm going to have one section. And this is going to hold all my images. So I'm going to give it the class name of images section. And then let's have a another section. This one's going to have the class of input container. Just like so. And I'm actually going to put in the input here. Okay. And then a div and I'm going to overlap this div later on, which is why I put them both in an input container. And let's give this div the ID of submit icon, just like so. And I'm just going to put some text symbol in here. If you would like to use it, you can get it at this URL. It's just this little arrow that looks like this. So you can get it from here if you would wish. Okay, so at the moment, our input and our title are showing up here, that's because we need to position some stuff and use display flex to center everything in here in a much nicer way. So let's do it. So we are done with this for now, we are not going to put in any images, because we're going to use JavaScript in order to do that for us. So let's carry on. Now we are going to essentially on the body, well, I just want to make sure that everything is stacked on top of each other. So I'm going to initialize flex box so that I can use flex direction column, okay, without this, I won't be able to use this. Next, I'm just going to set the width and the height of the browser. So view width is going to be 100% of the viewport width, and the height is going to be 100% of the viewport height. Okay, and that means I can now use justify content center and align items center, okay, to center everything to the very center of my browser. Again, I need to assign a width and a height in order for these to work properly. So now everything should be in the center just like so. Okay, and we want to exclude the SVG from this. So I'm just going to grab the SVG. And I'm going to essentially just give it a position absolute top zero, left zero. Okay, I'm just going to make sure that it's always behind everything. So I just give it a Zendenix minus one, or minus 10 to be sure why not. Okay, great. So now that is in the center. Amazing. The other thing I want to do is just maybe in the header this time, I just want to make sure that all font in the header is going to be white. So let's go with color. Let's go to RGB 255 255 255. So that is something that I have done. Great. Let's also assign a height. So I'm just going to hardcode a height of 150. And I'm going to center everything in it by initializing flex books again. And now I'm just going to align items center. So this time is going to center it on the opposite axis, so from top to bottom. So at the moment, it will look like that. Wonderful. So this is looking great. Now, what other things I want to do? Well, I'd quite like to space out all the child elements of the body. So excluding the SVG, that would be the header and the two sections, and I would like them to the spacing to be even between them. So I'm going to use justify content space between. So on the body, I'm going to change this to be space between. So they are spaced out like so. Wonderful. This is looking great. The other thing I'm going to do is just change the font family on the whole body itself. And let's go with trebuchet. And as a backup, I'm going to have sans serif. So just one backup. So that will just change the text to be a little bit more like this. Next, let's start up so the images container maybe let's leave that for now. Let's do the input container next. Okay, so let's do it. In fact, I think the input container, let's wrap it in a another wrapper. So in fact, let's make a section. And I'm going to give this the class of bottom section, just so that we can center this whole input container inside of it. So maybe let's change this to be active instead. Okay, so there we go. So now if we look in here, the three child elements are the header, the section and this section as well. So let's pick out the bottom section, of course, we are discounting the SVG as we've positioned that separately to the rest. So here, I'm just going to minimize that I'm just going to grab the element with a class name of bottom section. And I'm just going to make sure that the width of it is 100% of the parent element. And let's also use display flex initialize flex box, so that we can then use justify content center to center everything from left to right. And I'm also going to assign this a height of 150 pixels as well. So there we go. There's our bottom section. And there's our header. Again, header, bottom section. Wonderful. Let's work on signing the child of the bottom section next, which is the input container. So again, I'm just going to grab the input container by the class name. So the whole element that has the class name of input container, and I'm just going to make sure that the width is 100%. But I'm also going to give it a max width, so that it stops at 650 pixels, if we wanted to. Okay, I'm also going to give a position of relative. This is because I want to position the child inside of it, relative to the parent by using position absolute on it. So what I mean is, well, if we grab the item with the class of submit icon, and I give it a position of absolute, and I actually fix it. So let's go ahead and fix it to the parents or the input container top by 10 pixels and right 30 pixels. Where do you think it will go? Well, here's the parent, it will go 10 pixels from the top of that blue square and 30 pixels from the right of it. So there essentially, okay, great. Now let's also style the input itself. So let's grab the input. And I'm also going to give it a width of 100%. So just like so. Maybe let's change this to be a bit smaller. So 600 pixels. I'm also going to give this a border of none, as I don't want a border, I'm going to make sure that the font size in here is 20 pixels. So quite large, maybe, or larger, let's pad it out by 10 pixels. I'm also going to add a border radius to smooth off the edges. And that's going to be of five pixels. And I'm going to add some box shadow because why not? I'm going to RGB. Let's go with this kind of dark color. So 38, 57, 77, zero on the x axis, 20 pixels on the y axis, 30 pixels blur and minus 10 pixels spread. Okay, and at the moment, it will look like this. However, I want it to be on the inside rather than it's spilling over the parent. So for example, I'm just going to show you there's our bottom section, right the input container, which holds the input that's spilling over the bottom section. So I'm going to use box sizing border box to stop that from happening. Okay, so now it is in the parent and looks like this. So much better. Let's also make sure that the headers width is also 100% so that it takes up the whole space. And now we can also center that title. So let's do justify content center. Okay, and wonderful. So this is looking great. Let's get to hooking this up with JavaScript next. So let's do it. So all I'm going to do is in here, I'm going to show you how to get your API key. So we're going to need to go to open AI. So just make sure to go to OpenAI, and click on API reference, I've already got it up here. And now under here, I'm just going to view my API keys. Now I can create a new key, sure. So all I'm going to do is create a new key like this. And that will get created for me. Okay, great. And you're just going to copy it and keep it safe. Okay, you don't want anyone stealing this because they can use all your free credits, or rack up money on your credit card if you have a credit card attached to this. And you can of course delete them if you think yours is compromised, or you just don't want them anymore. So make sure to do that, I'm just going to save it here. So const API key. Like so, make sure it's your string. And I'm just going to remind you to not put this on GitHub, okay, do not deploy this API key or upload on to GitHub. Okay, this is just for personal use, because of the issues that I set before. So there's our API key, we've got it. Now let's get to using it. So what I'm going to do is, well, first off, I want to essentially get an image if I write something in the input and click on this button, right. So let's pick out this button by the ID, because we're going to attach an event listener to it. So I'm going to use document query selector, I'm going to look for anything with the ID of submit icon, just like so. And let's save it as submit icon, so that we can work with it in our JavaScript. Now, so I'm going to get that and I'm going to use add event listener. So listen out for clicks. And if we click on it, I want to get images. Okay, so now let's define the function get images. So const get images, I'm just using a function expression, you can write function if you want. And what we're going to do is try something and catch the errors if it doesn't work. Error. And we'll just console erroring the error. So that's all I'm going to do. So if we click on that submit icon, so if we click on it, that's the event, we're going to call this function. At the moment, it's not doing much because you know, we need to write this code. So what we're going to do is make a request. Okay, we're going to make a request to the DALL-E model. And that is to API references. And then we're going to find images. Okay, so this is what we need is a post request to this URL. So let's grab this URL. And now I'm going to use the fetch API keyword to fetch from this URL, I'm going to have to pass through some options in which we define the method, which is going to be post as we just saw. So const options, method, it's going to be a post method. And next, we're going to also have to pass through some headers, right? Because we're going to have to pass through that API key. And we're going to do so. So we're going to write authorization, make sure to spell that correctly, authorization. And then we're going to do back ticks, as we're going to use the word barrow. And then also pass through that API key. So to pass through code or variables, we use the dollar and these two curly braces, and then we're going to pass through the API key. So that will come back as barrow and this string with a space. Next, we're also going to have to define the content type because we're working with JSON. So content type, and then we're going to do a location. Okay, so that's what we have done. And then we're going to have to have the body. So the body, well, I'm just going to pass through an object, and it's going to have a few things, it's going to have the prompt itself. So the string that we want to send to the AI, so like generate a cat or something. So we're going to put that here. Next, we're going to have n, which is going to be the number of images we want, I'm going to put four, and then we're going to have to add the size and the size of this is going to be where there's three we can choose from. If you look here, here are the options, only the prompt is required, right? So the make us a cat, these are optional, but I divide n as four, because I want four images, and the size you can choose from these three, I'm just going to choose the biggest, you can have all these others, but you know, as a default, we are going to be returned the URL to the image. And I don't really care about the user being shown for that. So great. So let's put in this size, as that is the options we need. And I'm going to have to wrap this through JSON stringify. Okay, so there's a method called JSON stringify. And then we're going to pass through this whole object through it so that it kind of JSON buys this for us. So there we go. Now the prompt, of course, I can write some text, but that's not very fun. I want to get the value from this input, right? So let's go ahead and do that. There's only one input. So I'm just going to pick it up by the element self document query selector. And I'm going to look for an input. Okay, and let's save this as input element, just like so. So now I can grab that input element. And whenever we click on it, let's hope there's something there, right, this input element, and we're going to get its value. Okay, so when we click on the little arrow, we hopefully have something in the input element. Otherwise, you know, you're just sending an empty string. And then we're also sending through the amount of images you want and the size of those images. So great. So those are the options. So we're passing through the URL and the options as a second parameter fetch is an async function. So we need to use the await keyword for this, we need to await for it to come back. And as we're using the await keyword in here, this also needs to be an async function. So if you want to know more information on that, I do have some async await tutorials on my channel. So once that comes back, we're going to save this whatever comes back to us under the const response. Okay, so we're getting the response. And once we get that response, we're going to get the JSON from it. But oh, this is also an async method, we're going to have to await it. So we're going to await that JSON and save the return under data. And for now, let's just console log data. So there we go. Let's check it out. So all I'm going to do is back on here, let's go pictures of blue cats in the rain. And click console log as well. Okay, so that is done. And we get for URL, this is great. And if I get one of these URLs, and put them in here, we get a picture of a blue cat in the rain. It's so sad. Wonderful. So this was I'm also going to just add a cursor to this. So on the actual submit icon, I'm going to add a cursor pointer just so it's obvious that we can click on it. So that should show up. Wonderful. So now let's get to using these URLs and mapping them onto images here. So let's do it. So I think once we get that data, right, so data exists, we're going to get the data from it, because if we were to look in here, I'm just going to click on this again, a blue cat. Okay, and let's wait for that to do its thing, we want to just see what returns back to us. So we can work with it. This is data, we then need to go into dot data, right to get this whole array. So that's why I've gone data dot data, if data exists, we're going to go into data, and get that whole array. And for each item in that array, which we call each item, we can call it wherever we want, I'm going to call an image object, as that's essentially kind of what it is, right, it's a object that holds just the URL. So for each of those, I'm going to actually create an element, I'm going to use document create element, and I'm going to create a dip. That's right, that's what I've done. And let's say this is image container. Because each of my images, I'm going to put in a container so that we can kind of crop it out if it's too big. So now let's grab that image container, and I'm going to give it the class list. And I'm going to create a class that is called image container. Okay, so that's what I'm going to do. And once we have that image container, we're actually going to put a another element, a a image element inside of it. So let's create it document create element image. And let's call this image element. And now let's grab the image element. And I'm going to set attributes. So JavaScript methods called set attribute to set the source, and then whatever the image object URL is, okay, so I'm getting the URL. And I'm essentially getting image object and adding source equals the image URL. And now I'm going to get that image container. And I'm going to append I'm going to put in that image element into it. Okay, and once that is done, I'm actually just going to pick out the whole image section by its class name. So let's do that. I'm going to do so up here, const image section equals document query selector. And I'm going to look for something with the class of image section. So then I'm going to grab that image section. And I'm going to append the image container I just stuck the image into. Okay, so let's have a look at what this looks like before continuing, right? So maybe let's get rid of this console log now. Go in here. And a orange hot dog. Let's wait for that to do its thing. And great. So obviously, we haven't styled it at all. I'm just going to show you what happened. So this image is section which at the beginning had nothing in it now has four elements inside of it. It has a div, we created a div for every item in that array, right, we created the div, and we gave it the class list out of image containers, we added the class of image container to it. Next, we also created an image element. And we added the attributes, so set attribute of source and a URL that we were mapping over. So that's what we did. And then we put that image element in the element with the class of image container. And then we put that image container inside the image section. So we did all that with JavaScript, which is pretty cool. So now we have our four images. And let's just start this up. So what I'm going to do is perhaps grab the let's grab the images section. So let's go ahead and grab that. And I'm just going to say that the width of this whole section is going to be 100%. But also, I'm going to set a max width, and it's going to be 600 pixels. So just like our input. And now I'm going to use display flex to initialize flex box. And I want everything to wrap over each other. So I'm going to use flex wrap wrap in order for it to do that. And then I'm just going to space out everything evenly with space between and also just pass this out by 10 pixels. Okay, great. And finally, I'm just going to do a few more things. So I'm going to grab the image container. So the thing that holds our image, I'm just going to give it a width of 40% of the parents of the image section. So each one's only 40%. I'm going to round off the edges with border radius is round off by 15 pixels. Let's hide any overflow. So if it's a square image is a square that is inside of I want to hide off those edges. And let's just give it a box shadow, I'm going to go with RGB 385777 as the color, and then zero x axis 20 pixels y axis, 30 pixels blur and minus 10 pixels. And finally, I'm going to say that any image lives inside of the image container. And let's just give it a width of 100%. Okay, great. Maybe let's change this to be 48%. I think 40 is maybe too small. And let's test it out. Just make sure that you know, you are using the same quote marks anywhere, just before sharing this with anyone before you don't need them here. So let's get rid of those. So we can do that. Just clean this up a little bit. And this should be small. So let's just change that also. And then just make sure that if you're using hex and RGB, just try to make sure that it's the same approach you use each time. So great, that is looking so much better. I'm just going to change these out to just to make everything a bit more consistent, rather than just me speed coding this through for you. Okay. And wonderful. And let's test it out. Let's watch we do let's do a rainbow ice cream. And wonderful. So I hope you've had fun building this image generator. Of course, this is just for demo purposes, we are going to be building the same thing. But with added functionalities, we're going to be building a dirty clone that will do this, but also allow us to upload existing images for variation in reacts with a node.js backend, as well as using the OpenAI node.js library next. Hi, everyone, and welcome to this tutorial from Cape Town in South Africa. And in this video, I can be showing you how to build a daily clone essentially. So an AI image generator that will take prompts and generate images for you, we're going to be generating lots of images based on this text prompt. And we're also going to add a another feature that allows us to take an existing image and upload it and then create variations of that image format. Okay, so really excited about this, because we're going to be using the OpenAI API for this. So you're interested in learning how to use it. This is the perfect tutorial for you. We're going to be building this in react for the front end with a node.js backend so we can keep our API key safe. So what are we waiting for? Of course, if you don't have the fundamentals of react and node.js down, please do try this out anyway, and fill in your gaps of knowledge later on. I do have a course that covers all of this. So check out the link in the video description below if you wish. Right, so first off, I'm just going to start a new project, it's going to be a react project. So all I'm going to do is because I'm on WebStorm, just click react. And what should we call this, I'm just going to call it react, Darlie clone. Okay, and I'm essentially going to use this command to spin up my project. So in WebStorm, I don't need to do anything, I just need to click create. And then that will spin up my react app. Now, if you're not using WebStorm, just go ahead, I'm just going to make this bigger, and go to the directory of your choice. So for me, it's going to be with some projects, and then do npx space. So it's two commands, create, react app. So just like we saw, and then whatever you want to call your projects. So you can do react, Darlie, clone, or whatever you want, and hit enter. And that will do exactly the same as what is happening here. Okay, and then you'd have to go into that project. So cd into this project and open it up. So that is just for those who are not using WebStorm. Okay, but I am so I'm just going to continue and wait for all my files and configuration to populate in this directory for me so that I can spin up a react project. Okay, if this is a bit too much of your new to react, then please do check out my full site developer course where we go into this and a lot more detail than I'm going into now, of course, I'm just assuming that you have the fundamentals down for the act. But if you don't, then no worries, please watch along anyway and fill in the gaps of knowledge later on. So there we go. Happy hacking, we are done. And if we look in here, we see all the files and folders are ready for me to use. I'm just going to clean up and delete the ones I don't need. So let's just go ahead and delete these because we're not going to write any tests. So delete that delete the logo, delete, delete, delete any way, delete, let's go ahead. And yes, we don't want the test file so that can go. And I'm going to delete the app CSS file, because there's not going to be much styling, I'm just going to do it all in one file. So now your industry as file, I'm just going to, again, delete this because we don't need it when it deletes semicolons, because I don't like using them. And there we go. So that is your index.js file should look like at the moment, let's get rid of everything in the index CSS. And your app.js, again, I'm just going to delete most of this, like, so we don't have a logo, and we don't import the app CSS file. I'm also going to change this to be a functional expression, just because that is my personal preference. So this is what your app.js file should look like. This is where your index CSS file should look like. And this is what your index.js file should look like. You can change this to be JSX files as essentially we are going to be using JSX. This is JSX. That is totally up to you. I'm not going to because I just want to get the project done for you. So we can learn how to use OpenAI, but it's up to you. So there we go. That is what we have at the moment. Let's carry on. So first off, I'm just going to sell this up. Let's work on actually generating images first. So let's do it. So what I'm going to do is just essentially build a kind of input that looks kind of cool. And I'm going to do this by essentially creating a section. So we're going to have two sections. We're going to have this to be the search section. So I'm just going to give the class name of search section, just like so. And let's have another section. And there's going to be to show all our images. So I'm just going to give this the class name of, and let's go with image section as our images are going to be spilled out into here. Now in the search section, I'm also going just to put a P element that says start with a detailed description. And then I'm going to open up a span element that says surprise as well if we want to be surprised with a prompt instead. So there we go. Or maybe let's just have surprise me, surprise me. Okay, so that's what that is going to say. Let's also just pick this out. So I'm going to give this the class name of surprise. So we can pick it out. So we can style it surprise. I'm just going to put this on a new line for you like so. And also, we're going to have an on click on here. But let's maybe leave that or perhaps let's do it. Why not? Let's have some options to be surprised with. So I'm going to write surprise options just like so and make an array. And then in the surprise options, let's have a few commands that we can pass through. So I'm just going to have three strings in this array. A blue ostrich eating melon. Let's have a Matisse style shark on the telephone. Intrigue to see what that's going to look like. A pineapple sunbathing. I'm looking at the sun now. So I'm going to go with sunbathing on an island because I'm in Cape Town at the moment. And I've got the most amazing view of the sea. So I guess that's where that has come from. ostrich. Hopefully haven't made any sudden mistakes. So we have now have some surprise options. And what I want to do is on click of this, I want to essentially bring back one of these so we can populate it. But let's leave that for now. I just want to carry on building this out a little bit more first. So there we have our p element, that whole thing right here is going over three lines. And after p element, I'm actually going to create a div. And it's going to hold our input as well as the button to generate a new one. So I'm going to give this the class name of input container just like so. And in my input container, I'm going to have an input, which is going to take up the majority of the input container. But on the right of it, I'm also going to have a button that's going to say generate and it's going to generate whatever images we want based on the prompts we give. So those are my two things that I'm going to put in here. Maybe let's also have a placeholder for this. So just so you know what kind of inspiration I guess for the prompt, let's have an impressionist oil painting of a sunflower in a purple vase dot dot dot. Again, I'm just going to put this on a new line because I want you to be able to read everything. So that is one thing that we're going to have on the input and the button again, there's going to be an on click on here. But other than that, I think we are now done. We just need to start this up a little bit. So let's go ahead and first pick out the app. First off as well, I'm going to also just grab the whole body. So the whole body of the app that we are building, let's make it a bit bigger. And I just want to get rid of any default margin and padding. So I'm just going to go with margin zero, padding zero, that's actually very large, we don't need it that big. I'm also just going to make sure the whole body takes 100% of the viewport width and 100 of the viewport height. And then let's also give a background color, I'm going to go with a slightly off white. So f a f a f c is what I've chosen, you can kind of see the preview here. And I'm just going to make sure that all the text is also the same color. So this kind of gray. There we go. I'm also just going to make sure that everything so star means everything, everything in here is going to have the font family of Sans Serif. You can have a backup, I can't be bothered. But if you want, you can of course have like a few more here as backups of Sans Serif. But Sans Serif is a pretty stable one. I think all browsers are compatible with it. So great. So that is my body. One other thing that I'm going to do is actually say, so at the moment, let's start this up, I could just go ahead and click here. And that will run the command NPM run start for me. So this command right here. But if you are not in WebStorm, of course, you need to go into WebStorm projects again and find react-darley-clone-open-ai. Okay, so just go ahead and do that, making sure to spell that correctly. And once you're in here, you will do NPM run start to start up that project. Again, I don't have to, I'm just going to click here. And that will open that up for me. So there we go. It's opening up on local host 3000. And there we go. That's what it looks like. I'm going to inspect the page so we can view the console and see what's up. So this is what it looks like at the moment, our elements are here. And if you move this down, you will see in the body, okay, we have the root and the app is injected into there. And then we've got the search section, and the image section, which doesn't have anything in it at the moment. But let's start these up a little bit more. So I'm just going to minimize that and keep that running. And now let's get the search section, just like so, it's going to minimize that. And the search section, I'm going to make sure that the width is 100%. And then I'm going to center everything in this, I'm going to initialize flex box. And now I'm going to do flex direction to make sure that everything sucks on top of each other. So like a column, and I'm going to center everything using justify content center. So at the moment, that is my search section, everything is centered from the top to bottom. And now what I'm also going to do is get the parents of the app and make sure that these two are kind of not going all the way to the sides, I actually want the app to be only 90 to be only 90 of the viewport width. So let's grab the app itself. So the element with the class of app, and I'm going to sign the width of 90 viewport width to it. Okay. And now just center it in the body. So let's grab the body again. And use display flex, justify content center. So now that should be centered. So great, that is what it looks like at the moment. Let's get to styling the span with the class of surprise me next. So once again, I'm just going to find the element with a class of surprise. Because that was a class we are applied to that. And I'm just going to make sure that the background color is a color that I have picked out previously. So there we go. I'm going to make sure the font is black. I'm also just going to round it off. So it looks more like a pill by giving it five pixels border radius. So border radius, I'm going to make the font weight a lot heavier. So I'm going to pass through 600. And let's give it a padding. So I'm going to pad out four pixels from the top and bottom, and 12 pixels from the left and right. So that is a shorthand to do that. So at the moment, it looks like this. And I'm also just going to apply some margin to space it out. So I'm just going to use margin zero on the top zero on the right, but two pixels at the bottom and five pixels on the left. So that is what it looks like at the moment. This is looking pretty good. Now let's start the input container. So what I'm going to do is let's go back in here and have a look at this, let's grab the input container. So there we go, the element with the class name of input container. And I'm going to say that I want the width of it to be 100% of the parent that it's in. So the search container. Let's use display flex initialize flex box. And that just means that anything in the input container, so the input itself on the button will be next to each other. And now I just want to round it off. So give the whole thing a border radius of six pixels. However, it does have an input inside and a button inside. If those two elements go over the outline of the input container, I want anything that goes over to be hidden. So I'm going to do overflow hidden. So that just means that as you will see here, the little corners have been cut off because they go outside the input container itself. So here is my input container. And as you will see, that has been cut off. Now let's dial the input and the generate button next. So let's do it. One last thing, though, is I am going to add a box shadow to here, I'm going to go RGB a for transparency, we're going to go 0082 as the color, and then 0.15 of opacity. And I'm going to apply zero on the x axis, two pixels on the y axis, four pixels blur, and then zero spreads. So we can just leave that. And this cool box shadow will be applied. Now let's actually style the input. So let's grab the input. We can say that it's an input that lives inside the input container just in case we want to add different inputs later. And I'm just going to go with border non. Let's give a padding from the top 13 pixels and from each side, 14 pixels, making sure this will pan in correctly. And then the box size it I want this to happen on the inside. So I'm going to use border box, and the font size as well, I'm going to apply is 13 pixels, or maybe let's make it bigger 15 pixels with the outline of the actual input being none as well. So this just means that let's just comment this out for now. This just means at the moment, you will see a blue outline, I want to get rid of that if I interact with it, which means I can outline none, let's just make sure we spell outline correctly for that to be applied. So now no blue line will be applied. Great. So that is my input. The other thing I need to change is the width of it, I want to be 90% of the parent, which is the input container. And let's just change the font weight of this to be 200 as well. So there we go. So if this is width 90, let's make the button that lives inside the input container a width of you guessed it a width of 10. And let's style it up as well. So at the moment, it will look like this, but let's style it up further. So it looks less horrible. So one other thing, however, is on the input itself, I'm just going to change the placeholder text. So if you ever want to change the placeholder text, you can. So at the moment, obviously, let's just click off this, it looks like that, we can go further and just change the color to be a bit lighter. So I've gone ahead and picked out this color like so. And let's make the font weights. Well, 200, I think that's already applied, but it should just look like this now. Wonderful. Okay, so we have the button, I'm also going to just change the border of it to be none. Let's change it to have a border on the left, though. So we're going to override that none and give it border left of one pixels, the color that's kind of the same as the color, well, exactly the same as the text placeholder color and make it solid. The background color of the button, I want it to be white. Let's me give it a color. So the text should be this color. Let's make it bold. So let's give it a font weight of, well, you can go bold, or you can choose an exact font weight that's up to you. And I'm going to make sure that we it's obvious to someone that we can click on it by adding cast up points. So if we go over it, my cast changes. Okay, great. So that is cool. And let's just change that if the button is active. So let's grab all of this and say that if the button is active, I just want to maybe let's just change the background color. So background color, and let's go with this kind of color, like so. So if we click on it, it just does that. But this is good so far. I'm really enjoying it. Okay, some generic stuff I'm going to add is perhaps let's just change all the p elements in here to have a font weight that is applied as like a default. So font weight, I'm going to go with 200. And let's also change the font size to be 14 pixels. So that is just going to be applied a little bit to all of the fonts as a default. Wonderful. Okay. So I think this looks looking good for now. Let's carry on. So I think it's now time to actually generate an image so that we can see all the images showing up. So let's do that next. For this, I'm actually going to build out a backend. So in here, I'm just going to create a new file. So on the same level as the package JSON, I'm going to get a file and call it server j s. And our server is essentially going to go on here. So there we go. That is our file, there is where it lives, just make sure that it's not in the source directory, it's outside. Great. So let's minimize that. Now what's going to go in my server j s file, well, let's set it up, we're going to have to define a port. So I'm going to go with port 8000. We're now going to have to require some packages. So cons express equals, and then I'm going to get the package express. So we're going to do require express, as well as a bunch of other packages. So maybe now is a good time to actually install those packages. So if you get up your terminal, making sure that you're in the correct project, just do NPMI, and we're going to install the package express, we're also going to install cause so express is going to help us with rooting cause is going to help us with error messages that we get from cause, we're going to use the dot env file. So we need the dot interview package for this in order to hide our secret variables, so we don't upload them onto GitHub or anything like that. And we're of course going to use the OpenAI package that was helped us communicate with OpenAI better, as well as a package called FS and Malta, which will help us deal with actually storing images into our project. But we'll come onto that later. For those of you who need more of an explainer into these packages, and what we're doing here, please do check out my course, where again, I go into this in a lot more detail, but just not enough time for now. And it really is the kind of fundamentals of working with express and Node.js. So I'm going to hit enter for that to do its thing. And essentially, you should see those dependencies or those packages show up here, along with a version we are using. So if your version is different for any reason, please go ahead and change that. Make sure that they're the same if you're watching this in the future as this video, because something might not work. And then just right rerun it. So reinstall them again, if you've already changed the package. So if I change the package here to three, save that file and run NPM, that is the version that will get installed. But of course, we don't want that we want the latest versions. So great, we have now installed those packages. Now I'm going to write a script in order to start our back end. So here's our front end, but I'm going to change it to be start front end. So I'm just going to make that a bit bigger for you. We're also going to have to install one more package, which is no demand, which is going to listen out to constant changes on our back end. So please go ahead and install that package, which means we can now use it to start our back end and listening out to constant changes. So now I'm just going to do start back end. And I'm going to do no demand and no demand listen up for constant changes. And I'm going to see on which file I'm going to see on the server JS server JS. So that's what that piece of code is done. And there's the node amount package. So save that file. And now I'm actually going to stop this from running, because I'm going to run my front end from here. So I'm going to do NPM run, stop front end this time NPM run, stop front end and hit enter. So now our front end is running again. And you will see that is running and I'm going to create a new tab making sure again that I'm in the same project and do NPM run this time start back end and hit enter. So there we go. Now we have our back end running and our front end running. So now back in here, of course, we need the package express. Next, I'm also going to require the package core. So let's do require and then the package of course. And now I'm going to get express because essentially, I've got the package and I've saved it under this cons. And now I need to release all that wonderfulness. So whoop, that's me releasing it. And I want you to store all that wonderfulness under something else I've gone with app, which means we can now use all of expresses wonderfulness by using app. And now app will have lots of cool methods and properties attached to it. One of them being app use, which will allow us to grab the cause package and once again release all of its wonderfulness and we can use it in this project. Okay, so hopefully I've explained that well. The other thing we need to do is actually use app use. And we're going to get express and release Jason's use the method of Jason on it. So we can actually work with Jason where we're sending Jason from the front of our project to the back end of our project. If you don't have this, you won't be able to send stuff from the front end to the back end, specifically Jason. So great. The other thing we need to do is require the package.env. And this will allow us to essentially create.env files to store our variables secretly. And we're going to have to do that because we're going to store our OpenAI API key. Cool. So I think that should be it for now. We do have a few more to use, but I think let's cross that path when it gets to it. So now I can, of course, use app and it will come with a cool method called listen, which allows to listen out to a port. So that is one thing we're going to pass through. And the second thing is a callback. And we're just going to console log. Your server is running on port, and then the port number. Okay, so let's check it out. So now if I look at my terminal, that shows up. And if I make any changes here, it will rerun it. So I just saved the project again, and this will rerun it. So that's what nodeemon does. Nodeemon essentially listens out for constant changes on our back end. Cool. So now that we have done that, let's get to using the OpenAI API. So all I am going to do is essentially go to the OpenAI documentation, let's go to developers, let's go to API reference, of course, making sure that you are signed in, right, so I hope you're signed in. And all I'm going to do is essentially, this is the we're going to create images first. So this is going to help us we're going to use the node JS for this. And this is the endpoint we're going to use to create images, we want to create 10 images. So 10 is a number we can pass through, we can pass through the number of images to generate, we can get up to 10. So let's go get to it. The other thing we're going to pass through is the size of the image has to be one of these three. And then as a default response, we're going to get a URL to the image, that's fine, we're not going to pass that through. In fact, we're just going to pass through the prompt, which is required, the amount of images we want to get and the size of the image. So that's what we're going to do. It's already kind of done for us here. So all I'm going to do is take all of this, again, make sure you are logged in, because we are going to have to get our API key from here. But essentially, here is the URL you need to be at images, create image, and then under create image, make sure you're no JS and literally just copy all this code. And then we're just going to write a route. So what's the route going to be? I think if we were going to use posts, let's say that if we go to forward slash images, you can go to whatever you want, right? That's up to you. We're going to essentially do this. Okay, great. Of course, we have to pass through a request and response that is just part of the syntax for using express routes. And we have to make this an async function as we're using the await keyword here. And as we know, to use the await keyword, we have to make it in an async function because we need to await for this to come back. So again, if you don't know much about async JavaScript that is in my course, please do check it out. I'm not going to go into it in too much detail here as I'm assuming you already have that knowledge. Cool. So that is my post route at the moment, what we are actually going to do is move all of this out so we can reuse it. So I'm just going to paste up here. And of course, we are going to have to have an API key, just going to get rid of that. You know, we just need an API key, you can name it whatever you want again. So at the moment, this should be the only thing that's in our express route. And I'm going to stick it in a try and catch. We're going to try this, and we're going to catch any errors. And if there are errors, we're just going to console error, the error, right? So that is looking good. Of course, we don't really want this, we want to send this from the front end. But that will, we will do that when it comes to the right time. And once we get the response, all I'm going to do is use res send, and then send the response data, data, I'll show you why, just console log the data to see what comes back. Okay, so actually, let's just console log the response, sorry. But if you actually look in here, you can kind of see the response. Okay, we get the response data. And this was the objects that comes back, and we just want to get the data, which is this array, which holds objects which have URLs in them. But I will show you. So cool. That is what happens when we essentially make a post request to localhost forward slash localhost 8000 forward slash images. But don't believe me, I'm going to show you. So let's do it on the front end, what I'm going to do is actually add an on click to here. So on click, what do I want to happen? Well, on click, I'm just going to get the images, right? So let's define get images. I'm going to do so up here. So const get images is what I am going to call this function. And once again, I'm going to use try and catch, I'm going to catch any errors. And we're just going to console error, the errors that come back. And then in here, I'm going to again, use await, because the fetch API essentially is an async functions, we need to await for whatever comes back to us, I'm going to save the response. So we're going to save the response. And we're using await keyword here, which means this needs to be an async function as await cannot live in a function that is not async. And like I said, we're going to go to HTTP localhost as we defined 8000 forward slash images. So that is the route that we made, we could have called it whatever, if you change it here, then of course, you need to change it here too. And then we're just going to pass through some options. So let's define those options, const options, just like so. And we're going to pass through the method, it's a post method, right? Because it's a post method here, we're going to send some JSON, which we're going to replace here. So that is why it's a post request. And along with the method, I'm just going to pass through the body. It's going to be an object, okay, that's going to send a message, which is essentially going to be the value of our input, right? So at the moment, I'm just going to go with blur, make sure that is inside the object, I'm going to have to rice wrap this in JSON stringify in order to send this whole object as JSON. Okay, great. And outside of this, we also need to pass through some headers just to tell this that we are working with JSON. So I'm going to do content type, then application JSON. So just like so. Cool. And once we get that response, I'm just going to get it to JSON. But oh, this is also an ASIC method. So we have to await it. And we have to await the response. Let's say this as maybe data. And there we go. And I'm just going to console log the data. So that's a lot. Let's see if it works. Of course, we aren't passing anything through. We're not even passing blur to the backend. Well, technically, we are. But that's not all we're saying to the API. Acute baby C otter is what we're sending to the API. So let's do it. Let's try this out. I'm just going to go back to my project, let's get up our console log. And then let's also not forget to get our API key. So I'm going to show you where to get that is just under here, we're going to view the API keys, and we can create a new one. So I've just gone ahead and created that, of course, this will not be accessible to you, I will delete this, I don't know, you can go and use mine and use all my free credits. But that is how you'd create one, okay, just go to account API keys and create a new key, copy it. And then I'm just going to for now, paste it here. Or in fact, let's just make the env file, I'm just going to create a new file, let's call it dot env, and add and then I'm going to define API key equals and then put that string we don't need to put it in quotations as the string is implied. And it just means I can now use process env, thanks to this piece of code right here, in order to look into my env file and find API key. So we find it and get its value. So that's all I've done. Let's carry on. So yes, now if I go ahead and click Generate, we should be able to communicate with our API. And we're just going to pass through acute baby C otter. And then we should get back to images for us. So if we look in the terminal, this is the whole response. However, if we go dot data dot data, like I said, we're going into the data object, let's try again, I'm just going to click Generate again, and let's have a look. So we're waiting for changes that will wait a little bit longer. And there we go. So we've got the data data. And here's our array of two URLs. And they should be of two cute baby otters. Let's have a look. Okay, so here is one, it is a cute baby otter. Wonderful. So that is working. And that's what we are sending back to the front end. So that we can use it here. So we can now map these two images onto here. So let's do that next. Back on the front end, let's actually just make this a bit smaller now, or actually just get rid of that completely. I'm going to use states. So let's go ahead and import the use state hook, import, use state from react. So we can save ourselves to the state of this component. So I'm going to do const, let's maybe save the, what should we call this, I guess, images, right, that's what they are images, set images, use state, let's start off with null. And now once we get back that data, so the response is data data, which is what we're console logging out here, so it's an array of two objects, we're going to use set images to just set that data, right. So now we're going to have images. And we can now get the images to show up. So all I'm going to do is in the image section, let's open this up. And then if essentially images exist, I want to map each image, we're going to have to get the index as well, because we're going to have to essentially map that onto a key. So let's get each image. And let's get an index, we're not really going to use this, I'm just going to underscore it. And then I am going to create an image element. Like I said, this is very simple. So you know, if you want to build this out and create components, please do this is just to get us used to using the OpenAI API. Let's go ahead and add in keys, I'm going to use index. And now I'm going to add the source and the sources of this is going to be the image. Well, if we look at what's coming back to us, here is my first item is an object. So we're going to use dot notation to get the URL. So I'm going to do dot URL. And as an alternative text, I'm just going to do generated image of and then I guess whatever my prompt was, right. So actually, what we can do is just put in the value. So the value is going to be my prompt, which of course, we haven't written yet. But I think that's kind of a cool way to do it. Right, because we need this for the visually impaired. So now, maybe let's just get the value. So I'm just going to say the value of the input up here to const value set value. And then let's do use state null to start off with however, we can set the value on the input change. So on change of this, I'm just going to get the event and then set value e target value. So that is how you would change the value of the input, we can also display it in here just by passing through the value. Okay, so now if we have a look, in fact, I'm just going to console log this out to up here console log value. Right, so at the moment value is null. But if I change this, it changes here. And that's what we can send over when we make a request. Cool. So we are saving the value and then we're just showing here, we're also going to save it here of the generated image once we have the images back. So now that we are mapping that on, let's have a look. So let's have a look here. Why is it shouting at us? Okay, so we want to essentially map those images right onto images. And that's what we are doing. However, let's also make sure that each image that lives inside the element of the images section. So let's grab the images section again. Okay, and down here, I'm going to grab the image section, and just make sure that it's with does span 100% of the parent, I'm also just going to make sure that everything wraps over each other. So I'm going to initialize flexbox for that. I'm also then going to make sure that it wraps over right. So I'm going to do flex wrap wrap. And then I'm also going to align items. Stretch, so they stretch out, and I'm going to justify content space between so that the images kind of stretch. Okay, but of course, we won't really be able to see anything until we get the images. So let's just say that any image that lives inside the image section is going to let's give each one a margin of one pixel. So there's space out from each other. Let's also give them a min width of 250 pixels, but then also a max width of let's say 33% of the parent. I'm also going to use flex grow to make sure that they stretch out. Okay, cool. Well, I'm also going to do so at the moment, we really won't see much. Let's maybe generate this again and wait for those little orders to come back. So let's wait in there will be hard to see with two. So maybe let's just change the amount that come back. Sorry about that. Let's just change it to 10 baby orders. And let's try again. So generate. Okay, and now we're gonna have 10. We're going to see what it looks like when there's lots of images populating our app. Because it does take a while for this API to do its thing, we are working with images as well. So it will take some time in order for that to show up. Okay. So there we go. Here's our 10 images. And here's our 10 baby orders. How cute is that? We should probably space it out from the top. But we will deal with that later. I just want to show you that this is what it looks like. And then we can even add media queries. So I can add a media query. Let's go back here. And I'm just going to do at media max with let's go with 556 pixels. And then I'm just going to say that any image that lives inside the image section is actually just going to have a max width of 100%. So it's going to essentially take up the whole space if I get to a certain point. Cool, right? Okay. What else do I want to do? Maybe let's also get the search section and assign it a height. I don't know, 300 pixels, whatever you think will look nice. So I think that looks okay. We can make it smaller. Like honestly, this is just styling that you can get way too wrapped up in when we just want to learn how to use the OpenAI. But you know, I think that looks better. So now let's actually get to passing the value through so we don't just get authors. I'm going to show you how to do that next. So let's go back to the app. And we are setting the value here, right? So now all I'm going to do is get that value and replace it with blur. So there we go, making sure that is code. And that now that means that's going to be passed over with our option. So on the server, that gets sent over. And it's part of the body, right? So if we look at here, it's going to be part of the request body message. And this is an object. So we use dot notation. So I can just go with using request body message to get whatever that value is. So this right here, make sure to wrap it in Jason's string of five and make sure that is here in order for that to work. But essentially, now let's check this out. So let's go back here. What should we do this time? I'm just gonna refresh this for now. Let's go with or let's do surprise me, right? Let's hook up the surprise me. So let's go back here. And on click of the surprise me so on click, I'm going to write a function called surprise me. And let's define it. So let's grab this constant surprise me equals and then all I'm going to do is essentially set the value. So set value to be well, I'm going to get the surprise me options or let's maybe yeah, let's get the constant random value from the array. I'm going to get the surprise options. And I'm going to pass through into them to get back a random number from zero to two, as there is index 01 and two. And to do that, I'm going to essentially use math, run, done and call it but multiply it by the surprise options. length, okay, and then round that number down because that will give this gives me back a random number from zero to just under one. And if I multiply it by the length, it would be from zero to just under three. But of course, regions exist, we want to round it down to two. So that's why I pass it through math. Okay, so that is how you would get a random value and we just pass it through into set value. So now if I click on here, how cool is that let's go with a Matisse style shark on a telephone and generate and wait for that to do its thing. And we get our 10 sharks. This is cool. And here they are. Here are 10 randomly generated sharks. I love them. They're pretty awesome. Of course, it will take a while for the images to download. But I mean, this is like super arty. And I'm really into it. Of course, we can write our own thing. So we can do a cool ice cream and generates. You will see how that value is updating every time we type it, but that value will only be sent once we hit to generate as well. So that is something that you should know. Okay, and then that's replacing the images here of cool ice creams. Okay, of course, we have to wait a little bit for that to completely be replaced. One thing we can do is when we click the surprise me, we actually set the images to be null. First, as well as I think when we get the images again, let's just reset that. And actually also, let's say that if value equals null, right, so if we just click it, well, there's no value, then we're going to set an error message. And then set an error message. And that error message is going to say error must have a search term, right? Okay, and I'm going to return out of this because we don't want to do anything else. So let's set error messages, const, error, set, error, use state, we're going to have a null to start, I'm going to set the error. And if we do have an error, I'm just going to display it down here, I'm actually just going to maybe display it, I think, let's go with just outside of the input container down here, I'm just going to show the error if one exists. So maybe let's wrap it if error exists, then we show the p element with the error. So no p element exists unless there's an error present. Okay, so now let's check it out. A cool cat and generate and wait for that to do its thing. And we get some cool hats. And if we click surprise me, it'll clear those images so that we can start fresh, and we can generate our surprise me prompt. Okay. And again, same if we want to remove this, some more cool hats, and generate, it will clear those images so we can start fresh. So that is a much better approach. Right. So generate 10 images, they look pretty cool. I think now I'm really excited to show you this next part as this. Well, this took me a while to figure out. So I'm excited to share my result with you. And it's all about generating variations of an image that already exists. So this was interesting, because we're gonna have to figure out how to upload existing images onto here, not just write prompts, and use the images, create image variation endpoint for this part. So let's do it. So first off, I'm just going to go ahead and add an input that will allow us to do this. So I'm going to show you how I would personally solve this part, I would. So this is the input, we don't want to do it in the input container, let's perhaps do it outside of the input container. So what I'm going to do is actually create a p element outside of the input container. So just make sure that is finished here. And here, what I'm going to do, maybe let's just format this a little bit better while we are at it. Okay, so there we go. I'm going to use a p element. And I'm just going to write, or let's actually also give this a class name. So we can pick it out, I'm going to give the class name of extra info. So just like that, we'll have all and then I'm going to actually create a span. But this span, so maybe let's put this on a new line, this span is going to hold a bunch of stuff, it's going to hold a label. Okay, and the label is going to say upload an image. Okay, it's all part of one sentence. So that's going to say upload an image and this label is for so let's use HTML for this is for something with the idea of files, it's going to be an input. Okay, with the ID of file, so that's how you would link them up. So if we click on the label, it will affect this input, I'm going to show you what I mean. And here, this is going to have files, but it's also going to have an accept. And it's going to accept all types of image. So I'm just going to go with image like this. And it's going to take the type of file. So at the moment, if I look at this, it will look like that, or upload an image, but I want to hide this part. Okay, and I want what I want to happen is if I click on upload an image, then it chooses an image for me without actually showing this part. So let's add hidden to this to hide that. Okay. And so all upload an image, and then I'm just going to put some more text. And that is going to say to edit. Okay, so there we go. Maybe it just needs a space to edit here. So I'm going to put a space there. Put a space there, ID match, otherwise that will not work. And it just means that now if I go ahead and click on here, that should open that up. Okay. And now what I'm going to do is actually grab this class of extra info. And I'm just going to make sure that the text is centered. So extra info. And then I'm going to go with text align center. So that we go that is now done. However, why is this not centered? Let's have a look back here. Class name. And wonderful. So now we can upload new images. This is great. Part one is kind of done. Now let's move on. So I'm going to go back in here. And what do I want to do? Well, if we click on this, I essentially, so if we click on this whole thing, I want a modal to pop up and a bunch of other stuff. So I'm going to do on change of this input. So if we select something from the files, make sure to type file on this input in order for this input to look the way it does, I'm going to upload an image so we can view it. So let's define upload image. So I'm going to maybe do so here. So let's get rid of that const upload image equals, and then we're going to get whatever, we're going to hop off to E, because we're going to get the E target file. So the files we uploaded. So if I just console log E target files, I'm going to show you what happens. So back in here, let's upload this test image. Okay, this is what comes back, and we just want to get that first item. So this, it's a file called test dot png. So there it is. So we could just go into this and get the first item from it, because we just want one. So there will always just be one because we chose to get a singular file. So there we go. So now that we have that file, what I want to do is create a form. So we can send over the whole form. So I'm going to do const form data equals and I'm going to create a new form data constructor. So now to append to this existing form data, I'm going to use append. And we are going to essentially append a file, so the property file, along with the E target file. So we're sending that over with the form data, we need to send that over the form data in order for this to work. You can of course send other stuff too, that is totally up to you. Then what I'm going to do is set the selected image. So set selected image. And I'm just going to pass through this so we know what the selected image is. And of course, we need to save that to state. So let's do const selected image, set selected image. And then we're going to use state no, because it's going to be nothing at first, we are just essentially storing whatever image we select to this component. Okay, great. And now all I'm going to do is just send that image to my back end. So what I'm going to do is use try and catch, catch any errors. And I'm going to use the await fetch. So we use make this an async function, and we're going to define a root on the back end. So once again, let's do app, it's going to be a post. And we're going to post to let's go to upload. And essentially, what's going to happen here is I'm literally just going to send this image here and save it to my server. So it's essentially going to show up here, okay, or we can put it in the public folder, we can put it wherever that is up to us. So let's also pass through the request and the response. And what else do we need to pass through from the front end? So yes, let's go ahead and use this. However, we have to find this endpoint as upload this time. And let's also pass through the options. So just as above, and let's define our options. So whoops, this is meant to be up here, and we're just going to console error error. So let's define our options as I said, const options equals and it's going to be an object. Of course, we have to wait for this response. And the options that we're going to pass through where we're going to pass through the methods, which is a post method, we're also going to pass through the body, which is just going to be our form data that we have and we appended the file to. And then I'm just going to console log the response so we can see it. But of course, we need to get that response first and get it to Jason. Call it and await this. And let's save this as data. Okay, so then we just console log the data again. Cool. So let's see if we can send that image to the server. And on the server, there's a few things we need to do, we're actually going to now have to require those packages. So let's move that up here. And then up here, I'm going to const FS require FS. We're also going to require a package called Malta, which is going to help us save those files. So require Malta. So once we have those two, we are now ready to start essentially adding files to our repository by sending them to our backend. So all I'm going to do, I did get this code from the documentation. So we're going to use upload and upload, we're going to define up here. So maybe actually, let's define it here where we define a bunch of other stuff. I'm just going to make this smaller for now. I'm going to do const upload equals, I'm going to use a Malta, and we're just going to pass through storage, storage and storage, we're going to also define, and we're going to be working with single files, right? So we'll do file single. Okay, so let's define storage now, Quants storage, and here's where we're going to essentially define where we want to store those files. So Malta disk storage, we're going to open this up on a possible object, I'm going to define the destination. The destination here is the syntax again. So again, I've just taken this from the documentation. I'm going to do CB, and then we're going to save it to the public directory in this project. So they're going to be saved in here. Okay, so that's what I've written. If you want to just be saved, you know, like in the root of your project, you could do this, right? So that is what you can do as well. So I've just defined where I want to save these files. Next, I'm also going to define how I want the file name to look. So again, I could do request file CB. And now I'm going to do CB now, and then I'm just going to use today's date and call it so I get today's date, plus I'm going to use this little line, this dash plus the original file name. So file original name. Okay, because if we console log file here, you will see the whole file object. So console log file, I'm going to show you what this looks like. Let's go ahead and just put in a string of file as well. So you can see a book better. So I believe that's it. Here are the things you will need. So those two right here. So now we can use upload that we defined up there. And again, request response and this policy errors. And this code I literally just got from the documentation. So if there's an error, just send back the errors. Otherwise, I'm just going to console log the request file. Okay, great. So now let's check it out. I'm going to go back here. And let's upload an image, I'm going to just go with this test or taste. Okay, so that's the file, and that should have triggered my request. So if I look in here, and let's look at the terminal. Okay, I believe that should have worked, I can see that we here's the date, right? And here's the dash. And here's my original file name. So that as well, that's the whole file. And essentially, I did file dot original name to get the original name, right? So that's what we did. File original name. So I've console log the file, I've looked in the object and got the file name, and appended it with the date now to create, let's look in public, this file, right here. So how cool is that? We've just saved a PNG file into our project. Okay, really cool. And like I said, if I just did this, and then let's try again. So let's upload maybe let's just pick the same file, taste.com.png. And now if we look in here, and let's just wait a bit, you will see that file is now in here, not in the public directory. But I do want them to be saved in the public directory. So I'm just going to put that back. So I'm just going to delete these for now. So we can carry on. But essentially, we are saving files into our project. How cool is that? Wonderful. So something I didn't say, and this is kind of important is that the images must be a certain size. So the three sides that we saw at the beginning, one was 256 by 256. So make sure your image is that size in order for it to work correctly, or the other two that you saw. Now, of course, this is a very basic tutorial on how to use the OpenAI API, it would be cool for you to be able to crop images in here, but it's outside of the scope of this project. So just make sure to upload the correct files if you want to build this out correctly. But we can view a few stoppers. So for example, let's put our modal that only allows you to upload certain size images next. So again, I just did that. And here is my image, it's got the date, as well as what I call the image, which is 256 by 256 PNG, which is the size of that image. So we are saving these images back here, the next thing we need to do is actually send them over to our back end. But before we do that, I actually want to build a modal first, so we can see the image and its preview. So what I'm going to do is in the source directory, I'm going to create a new directory called components. And we're going to build a modal. So components. And in here, I'm going to create a new file, I'm going to call it modal j s. And we are just going to build out that component. Okay, so we're going to add that. So let's do it, I'm going to do const modal equals. And then we're going to return some JSX. So at the moment, it's going to be a div, I'm going to export default modal. So just like that. Okay. And what do we want our modal to look like? Well, I'm just going to give this the class name modal, like so. And in here, I'm going to have a div. And we're going to actually use state in order to open and close the modal. So let's import use state from react, because we're going to have to save the I guess, I guess a few things. Well, we're gonna have to save any error messages. So let's just do error, set error, these errors are contained to this component, unlike on the app, use state, we're going to start off with null. So just like so. And actually, do we want to control? Well, I'd actually like to control a few more things based on whether the modal is open or not on the app. So we're going to pass through the set modal from the app itself. So let's go ahead and do that const modal open set modal open, use state, I'm going to start off with being false, of course, and this is not open. So cool, I think maybe let's start off with just importing this modal. So import modal from components modal. So now I can just use that modal down here. And where shall we put it? I guess it doesn't really matter too much, because we're going to overlay it with an overlay. So by that, I mean, I'm going to create a div. And in here, I'm just going to put in the modal like so, and I'm going to give this the class name of overlay. But I only want to show this if open modal is true. So we're going to wrap all of that in open modal. So sorry, modal open, it was not open modal. So modal open, and I'm just going to have this to be true for now so we can see what it looks like. So at the moment, of course, it doesn't look like anything because we haven't solved up the modal. So let's do that next. So I'm going to go back in here. And what else do we want in our modal? Well, I'm just going to have a div that says x so we can close it by the x. And on a click of this, I essentially just want to close this modal. So I'm going to close modal, I'm going to define the function here. So let's do const close modal equals one of few things to happen, though. And what I want to happen is I want to use set modal to be false. So set modal open, sorry, to be false, right, which means we need to pass that through. So let's go back here, I'm going to use set modal open, I'm going to pass it through into the modal so we can use it, which means we need to destructure that prop here, destructure it, so we can use it there. One other thing I want to do is set selected image to null as well, right, because we have, if we have a selected image, we don't want any more if we close the modal. So that is something else that we're going to have to pass through into the modal here. So set selected image, and then let's destructure it so we can use it there. Great. So that is what happens if we click on the x. Next, I'm going to have a div. And this is going to be for my image. So I'm just going to use the image element. And let's give this the class name of image container, just like so. Okay. And the image container is going to hold our image, which should only really show if a selected image exists. So selected image exists, then we want to show this, right, and as the source of this, we want to get that selected image and show it. However, so selected image, not set selected image, there's a few things we need to do. First off, we need to pass this through into the modal, right? So whatever we set here as a selected image, we are passing through into the modal. And now we need to destructure it here. So actually, if I console log what this looks like, our selected image, and what is wrong here, so we need to wrap this, okay, so selected image exists, then we show the image with a selected image, as well as some alternative text. Let's go with uploaded image. However, it will not work because so let's go ahead and do this. Let's go with this image right here open. Our selected image will look like this, because at the moment, it looks like an object like this, we need to pass it through URL, I'm going to show you URL, create object URL, and then pass that through. Okay, so we're passing that whole thing into here. So now we can see it. And great. So once again, upload an image. And then here's our modal. Let's also put in a button so that we can generate from that selected image. So after the image container, I'm going to just put a button that says, generate, okay. And let's sell this up. So first off, what I'm going to do is just grab the well, actually, let's grab the overlay first. So let's grab the class name of overlay, just down here. And I'm going to position this. So I'm going to give this position absolute top zero, left zero, I'm going to make it take up the whole width. So 100, you put width and the whole height, so 100, you put height, and give it a background color, a background color that is transparent, so we can still kind of see everything behind it. So let's go with black and 0.150 paces. So that is what it's going to look like. I'm also going to make sure we can't scroll by giving overflow hidden. Okay, so there we go. That is what it looks like at the moment. And we can't scroll thanks to overflow hidden. Next, I'm just going to center everything. So first off, I think let's initialize flexbox. Now I'm going to use justify content center, and align items center as well. Okay, so there we go. And the last thing I'm going to do just make sure it's in front of everything by giving it zen index of 10. Okay, just making sure that it's 100% in front of everything. So that's what it looks like. And if we close the here, it shuts the modal. Let's try again, let's open up a new image. Okay, that does not work. I wonder why let's refresh, close that. We are overriding this. So let's make this back to be false again. So we start off with the modal being closed. So let's go back to here and scroll down. As soon as we save that form data, we're also going to set modal open to be true. Okay, great. So let's try again. Upload. Amazing. And now let's start this up a little bit further. So all I'm going to do is now back on the index CSS after the overlay, I'm going to get to the element with a class of modal. I'm going to position it relative. I'm also going to make sure that the z index is the highest. So let's just go with 100 to be safe. Let's make the background color white. And now I'm going to give a padding of 10 pixels, a border radius to round it off of 10 pixels. Let's go with display flex. And I'm going to go with flex direction column to make sure that everything's stacked over each other. So at the moment, it should like this. And now let's style the button too. So let's grab the button that lives inside the button that lives inside the module. And I'm just going to make sure that the width is 100%. The padding is 20 pixels and border is going to be none. And now if we actually make it active, so if we click on it, I'm just going to change the background color. So let's go background color, and then f a f a f c. So that is much more, I think what it should look like I'm happier with that. Cool. I'm just going to change the x text icon. So choose one of these instead, just to make it look that little bit cooler. So let's go with maybe this one instead. And on the model, I'm just going to replace that like so. Okay, so that is better. Okay, so let's try again. Great. Let's also maybe make this background color white as well. So I'm happy with how this is looking, I'm just going to maybe go with cursor pointer for this to make obvious that we can click on this. The next thing we want to do is generate images based on this one, right? However, we want to set some error messages just to let us know that this image is not the right size. So let's do that next. So on the model itself, we are going to save the errors. And when do we want an error to happen? Well, I think let's also have another button here, as we want to check the size first. So when we click generate, we don't actually want to generate, we're going to add our click to check size. Okay, so let's define this check size, const check size equals. And then I am going to essentially use ref. So let's import use ref from react. So this means I need to initialize it const ref equals use ref. And then I'm just going to pass through null. And we're going to do so on the image itself. So ref equals ref, this is essentially the component that we care about, because we're going to get its size. Okay. And to do that, when we click check size, we're essentially going to say that if ref current width, we're getting its current width, and if it equals 256, and if ref current height equals 256, then we're fine, then we're good to go, then we can essentially write a function to generate variations. Okay, we're good to go on that. Otherwise, if it is not, well, then we've got an error. And I'm just going to use set error to set the error of error, choose 256 by 256 image just to be safe. Okay, so now we're setting an error and essentially when we want to display that error, right? So let's say that if error exists, then we want to or actually, let's have some text here anyway. So I'm just going to have as a default some text that says image must be 256 by 256. However, if an error exists, I want to override that. So if error exists, show that otherwise show that string. Okay, cool. Make sure it's in curly braces so it gets picked up as code. Okay, so now if there is essentially no error, then show this button, whether if there is an error, then we show this button instead. So and and that says, close this and try again. Okay, so and then on a click of this, we can just you guessed it close the modal. So we're reusing that function close modal. Wonderful. So now let's try upload something else, right? So upload an image, we're gonna go with this super long one. It's very large. Maybe let's actually control how these images are viewed, right? So I'm also going to say that the image container that holds our image is going to have a height of 256 pixels. Put that inside and a width of 256 pixels. And then I'm also just going to do overflow hidden. So it's really obvious that the image is too big, because it will look like this or look or cut off. And if I hit generate, it says error, choose 256 by 256 image, close this and try again. How cool is that? I'm pretty proud with what I built here. And then we can choose an image that is 256 by 256 pixels, and we can generate. Okay, so cool. Let's actually work on writing the generate function next. So we've defined the generate function here generate variations. However, we haven't actually done it here. So let's go ahead and do that. So for this, what I'm going to do is go back to the server and define a root. So let's do it. So as we saw that file console request file is being saved here, this is the whole file essentially, right, that's how we're getting the file name from it, we need to get its path. Okay, so I'm going to get its dot path. And I'm actually going to save this as something. So I'm going to save it up here, maybe, yep, sure. So let's go let file path at the moment would be nothing. But as soon as we have a value for it, so as soon as this runs, I want to get request file path and save it to file path, so that we can use it in our next route, which is going to be a post request. And let's define this, let's call this variations, you can call it whatever you want. And we're going to pass through the request and the response. And this, again, let's have a look at OpenAI for this. So let's look at the documentation. Well, we're obviously going to make a request to this URL. So we can just take all of this or copy it, make sure you'll know JS and copy all of this, this will create an image variation. Let's go back in here. And let's go ahead and use try and catch again. So try, I'm gonna paste that in like so we don't need this as we've already done that. And we've already defined OpenAI. So we just need the response, we have the await keyword there. So we need to make this an async function. And now let's catch any errors. So try, and then catch error. Console error, the error. Okay, so that's what we have done. And now we can get that response. And we're just going to send res send response, and the object so response data comes back as this, so we need to do dot data again. So response data data is what we need to write. Great. However, we know that we don't want to pass through this string, what we want to pass through is the file path that we saved up here, right? So the file path that we got here, when we upload the images, we got the file path was essentially the file path to any one of these files, the last one we uploaded. And then we're just going to pass that through like so. Okay, so wonderful. And we are hard coding this, let's get back 10 images all at this size. And once that comes back to us, so back in here, let's get the response. So let's actually hook this up to our front end next. So const generate variations equals and then all I'm going to do is try and catch again. So try and let's catch any errors. So catch error, console error, error. And we are going to try what we're going to use await fetch. And we're going to go to localhost 8004 slash variations this time, right? So make sure that is in a string. And then we're going to also pass through the options, which we are going to define. So const options, we know this is a post request. So options, method, it's a string of post. And we actually don't need anything else. So let's just get the response of this response. And then we're going to get the response. Don't forget to make this an async function. Let's get the response gets JSON. And this is, oh, again, async. So we use the await keyword. And let's get its data. And then I'm just going to essentially console log the data so we can see it. But I know it's going to be an array of images. So I can just set images to be the data. And once we are done, I'm just going to set error as null if there are any errors. And I'm also going to set modal open as false. So it shuts the modal. Okay, great. So when do we want to generate these variations? Well, we want to generate them after we check the size, right? So I'm going to go back to the modal here, I'm going to pass through generate variations, just like so, you know, let's maybe put these on a new line. So you can see everything that we're passing through into this wonderful modal. So generate a very shuns, I've obviously felt it generate very shuns. Okay, so that's better. And now on the modal, let's just copy it so I don't make any spelling mistakes. Let's pass it through here as well. And now let's essentially call it. Okay, before we move on, I am just going to also just set the images to null. So we can start fresh. And if selected image equals null, okay, when we try to generate the images, I just want a certain error message and just say that no image has been selected so that we can't generate anything, you can pass through whatever you want. This is the string that I am choosing to pass through so that it shows up. And finally, we're just going to close the modal. So I'm just going to use set modal and pass through false and return out of this so that we don't go to the next thing. And lastly, just so that we don't have any issues when uploading an image again, so the same image again, I'm just going to clear the files we selected. And we can do so. So right after we set the selected image, I'm just going to get a target value and set it to null. Great. So let's give it a whirl. So let's go back here, upload an image. Let's upload this image that meets the requirements and generate. And now let's wait. So once I've done this thing, it should shut this modal, it should get rid of any error messages. And it should show 10 variations of this image that I uploaded, which is pretty awesome. Let's be honest. And there we go. We can see those 10 images and those 10 URLs and 10 variations of me. How cool is that? I mean, some of them are like super scary, but you know, at least we have managed to do it. I've really enjoyed showing you this tutorial. It was really fun to make. It's been the funnest one I made in a while. So I hope you had fun. Thanks so much again. And don't forget to clean up your code, get rid of, you know, like we use RGB and hex. And we also used variations of different quote marks, and we haven't formatted the code. So please go ahead and do that. And take this project, make your own your style up. There's so much to do. It is yours. And then we can clear again. Okay, everyone, in this project, we're going to be using ChatGPT for to the GPT for model, in order to create this SQL generator. So this is going to be cool, we're going to be able to save our messages up here in the chat. And then we're going to display the final outcome. So the SQL query, we asked it to write in the little code section below. So that's what we're going to be doing. As you can see here, we can scroll through all our previous chats. And we can also clear the chat. Okay, so I hope you're excited. We're going to be building this in TypeScript for the front end and node.js for the back end, as well as the OpenAI API using the chat completions endpoint. Okay, so let's do it. Let's create a SQL generator in TypeScript with a node.js backend. So what I'm going to do is select a new project. And this is going to be a TypeScript project. So I can go ahead and click here and make it a TypeScript project by selecting this right here. So that's all I'm going to do. And let's go ahead and call this TypeScript SQL generator and hit create. Okay, so that will essentially spin up a TypeScript project for me. So let's just go ahead and wait for that to do its thing. If you're not using WebStorm, all you'd have to do is get your terminal up, find a directory you want to work in. So I'm going to go into some projects and use npx create react app, then whatever you want to call your app, and then dash dash template TypeScript. So that's all you'd have to do and hit enter. Well, I'm not going to do that because I've done it this way. So there we go. Happy hacking. And now you will see all the files that I need. We've got the TS config, Jason, or the package Jason. And then we've got the source directory. I'm just going to go ahead and delete what we don't want. So we're not going to write any tests or anything like that. So I'm going to delete these two. So this app CSS and the test file, then I'm going to also delete the logo. So let's go ahead and delete that. So just go ahead and click Delete. And then we're going to also delete the report of vitals and setup tests, as we're not going to need those either. So delete those two. There we go. Okay, great. So let's now have a look in my app TSX. I'm just going to pretty much delete everything so that we can start fresh. So there we go. Just delete all that. We don't really even need to import react. Let's change this to a functional expression just because that is my preference. So just like so. And then I'm just going to change the class name. So an export default, that component. Great, I'm going to delete everything from the CSS file. And in here, I'm just going to delete anything to do with testing or reporting with vitals. And I'm also going to delete the semicolon just because I don't really like using them. Okay, great. So this is what my index TSX will look like. This is what my app TSX will look like. And this is what my index CSS will look like. The next thing I'm going to do is actually fast off, let's just create the UI fast, this shouldn't take too long, I'm just going to create a few components. So I'm going to create a directory to keep all my components in. And in here, the components I'm going to create are going to be a code display. Okay, so we can see our code. Don't forget to use the extension TSX, as this is going to be type script file with JSX. And then I'm also going to create a messages display, they'll hold all our messages and messages, plural dot TSX, again, because we're going to have JSX in here. So just add that. And then I'm going to create a new file, I'm going to do this going to be for one individual message, the message display dot TSX. Great. So there we go, we've got three components. And I'm literally just going to copy this. And I'm going to paste that in here like so. So into the code display, let's change this to say code display. And then let's export that code display. And I'm just going to change this to say code display. Okay, let's do the same for messages displacement, copy all that click on messages display. And this time, I'm just going to change this to be messages, plural, messages, plural. So that's what the component is called. And I'm going to call this message just plural display. And finally, for the message display, where this is easy, I'm just going to make it not plural. So just singular on those three things. Great. So we've just created our three components, let's go ahead and import them into the project. So on the app. Well, I'm going to have to have a messages display first, because we want all the messages to display up here. So that has been imported for me automatically. So thank you very much for going into the components directory and getting the messages display component, we're going to pass stuff through into here. But for now, let's move on. I'm also going to have an input, okay, because we're going to have to want to, you know, send queries over. So there is my input, it's going to take a value, and it's going to have an on change. But we'll do that when the time comes. Next, I'm just going to have the code display. So there we go. Let's see if that's automatically inserted. And it is great. And one last thing I'm going to have is just a div. And this is going to be for our buttons. So I'm going to give this the class name of button container. So we can hold up buttons, we're going to have two in here. So I'm going to have one button. Let's give this the ID of get query, because it's going to help us get queries and get query just like so. And then another button, this one's going to be for clearing the chat. So I'm just going to paste that in. And let's give this the ID of clear chat. So we can start it up differently. And let's just change the text here to be clear. Great. So that is what it should look like. Now the messages display, so the plural, we're going to actually have a message display in here. So we're going to import message display from message display is we're in the same place, we're here, right? So we just imported from here. So we don't need to go into the components or anything like that. And I'm actually going to map all the different messages onto one individual message display. Great. Now let's do a little bit of styling. So fast off, what I'm going to do is say that everything in here, so everything in my entire project is going to have the same font family, I'm going to go with Verdana. And then as a backup, let's just have to Homer. And then let's have sans serif, good old trusty sans serif. And the text is going to be RGB. This is a color I picked out just as you're very dark gray, you could almost mistake it for black. Next, I'm going to say that any P element as well as the input are going to have a specific font size. So I want the birds to have the font size of 16 pixels. So that's what I have done. Next, I'm going to grab the whole body. And I'm just going to get rid of any default margin and padding just to make sure that there's no lines around our document. So margin, zero, padding, zero. Okay, and now I'm going to center the app. So for this, I'm going to use display flex initialize flex box, which means that now I can use justify content center to center everything from left to right. And now I can also use align items center to center everything to top to bottom. So on the cross axis, but for this to work, I need to give this a height. So I'm going to go with 100 viewport height of the browser. And let's just go ahead and give us a background color as well. I'm going to go with far, far, far. And we should probably change this to be RGB, right? Because I think let's try keep everything consistent. So 250, 250, 250, RGB, 250, 250, 250. Great. And now let's actually grab the app itself. So we're going to use dot notation to get that class name. And that app is going to be 80 of the viewport height of the browser and 80 of the viewport width. I'm also going to give it a background color. This time, it's going to be white. So two by five, two by five, two by five. Okay, let's also round it off a little bit, just slightly, let's go 10 pixels, just to not make it a harsh square. And it's also add a box shadow. Now my box shadow, I'm going to start off with being black, but transparent. So as for transparency, there we go black, I'm going to put 01.6 for the transparency. And we're going to also put zero x axis, one pixel y axis and four pixels below. Okay, so there we go. So at the moment, let's see what this looks like. In fact, let's go ahead and look at our start script. So if I do npm and start, it will start this. However, I actually want to add another script to start a back end. So start back end, let's just make this a little bit bigger, which means that let's change this to be start front. Now to start my back end in a TypeScript project, if I want to use type modules, I'm going to have to do TS node, and then ESM. And then we're going to read the index TS file, which we haven't made is a TS file, because we're not going to have any JSX in there. Okay, so make sure to have this if you want to add types, which I am going to do up here. So all I'm going to do is write type module, so that we can import modules in our index TS file. And by import, I mean, we're not going to use require anymore. So that's two things you need to do, you need to do this. And you need to do that. And we also need to import this package. So I'm just going to go ahead and do that. Let's do so in here, making sure you are in the project and npm i ts-node. So that's going to go ahead and install. And while I'm here, I'm also going to install calls and express as I know I'm going to need those two. So great, that is now done. So now let's actually get to creating this index TS file, which is going to essentially be our back end. So all I'm going to do is create a new file called index TS. So there we go, just make sure it's there in your project, so on the same level as the package is. So now to start my front end, front end, I'm just going to grab this. And in the terminal, I'm going to npm run start:frontend. And that should start at my front end, localhost 3000. There we go. That's what we built so far. I'm just going to inspect this for now, just so we can see a little bit more of what is going on. Great, let's carry on styling a little bit before we start adding the actual Meteor code. So let's go back here, I'm just going to minimize this for now. Get rid of that, just get rid of that for now. Let's style our code display. So I'm just going to grab the code display, just down here like so. And I'm going to give it a width of 96% of the parent, a margin of 2% to make up for the 100 taken from there, and a height of let's just go 46%. Let's see how that looks. I'm also going to round it off. So let's give it a border radius of eight pixels this time. And let's give it a background color. So again, I picked out this background color, I'm going to do the RGB 343434. Okay, great. And I'm also just going to hide any overflow. So overflow. So at the moment, it will look like this. Let's also add that little, I guess, header with the three dots just to make it look more like a little code display. So for that, what I'm going to do is well, I'm going to go to the code display. So just here, and I'm going to add a div. And this is going to hold some buttons. So let's go ahead and give the class name of buttons, making sure just fill it correctly, of course. And let's add three buttons. So this div is going to have the class name of first button, or let's actually give them all the class name of button that only more sense. So this is a button, this is a button, this is a button, this is going to be the first. So that's a separate class name, right? This is going to be middle. And this is going to be the last you can do first, second, third, it's up to you. Great. So that's what we're going to have. So those are the buttons in my code display. And after the buttons, I'm also going to have another div. And this I'm going to actually style as well, I'm going to give this code output. And we're going to want to put our text essentially, it's going to be a string in here. Okay, so there we go. I think we are done with this for now, I'm just going to minimize this, let's pick out the buttons first, and then the buttons and so on. So let's just get rid of that. I'm going to minimize this too. And let's get the buttons class name. So just like so. Now my buttons, I want this to span the whole way. And what's going to hard code a height, right? Because we don't really want this to change. And let's give it a background color of a slightly lighter gray. So there we go. And I want to make sure that all the buttons inside of appear next to each other. And for that, I'm just going to use display flex. And I also want them to align in the center from top to bottom. So I'm going to use align items center, because we're going on the cross axis. Next, I also well, actually, let's just, I also want the buttons or anything inside the buttons display to start a little bit from the left. So I'm going to give padding left five pixels. Great. So now let's pick out each button, each button, I'm just going to actually make a button. So circle, essentially, I'm going to make sure it's 15 pixels, which means that the width needs to be 15 pixels, because we're making a circle, let's go ahead and do border radius 50%. And then let's also space all these out. So margin, let's go four pixels. So this four pixel space around each one. Now, of course, if I was just to give this a background color of let's go with red, just like that, and have a look, we get three little buttons. But I've also given them all separate class names, as you will see here, first, middle, and last. So I'm going to now change the color by grabbing these class names. So I can actually grab the element with the class name button. And if it also has the class name of first, you'll see those are joined, I can choose different background color, I'm going to go to RGB 255 9686. And then let's do button middle it was and it's changed this to be 18945. And then let's do button last and change this to be 3820164. Okay, so there we go. This is looking great. Let's work on the messages display next. So all I'm going to do is get the messages, plural display. So let's grab that. And I'm going to make sure that essentially it's the same width as the code display. And let's also let's grab all that just so it's the same size exactly. And I'm also just going to add a scroll. So if there's more than messages that fit, I'm going to go overflow only on the y axis. And I'm going to do scroll. So the little scroll should appear. Okay, wonderful. Now let's style each actual message. So each message is essentially just going to be kind of a square with rounded off edges, I want to take up 100% of the parent. So 100%. I want everything inside of it to appear from left to right. Because I think we should have, you know, a p element in here that will show you the user, and then another p element that will actually show you the message itself. And actually maybe a third one too, that's just going to show some kind of icon. So I want these to appear next to each other, right? So let's also give this a closing p tag. There we go. So that's 123. And if I want them to appear next to each other, that's why we did display flex. Great. Let's also round this off a bit less your border radius five pixels. And I'm also going to do box sizing, border box, make sure everything's on the inside. And then I'm also just going to change the background color to be the same background color as I think the body, let's go ahead and do that. So I'm just going to paste in that like so. And now I'm also going to space out each message from each other. So each message block by five pixels from the top and bottom and zero from the left and right. So that is what that will do. Great. So if we look in here, now that's what a message will look like. And if I have many of these, so let's go. And here, let's just pretend that we have loads and loads of messages all of a sudden. Okay, that's enough. Okay, you will see it's scrolling, but I'd actually quite like the scroll to always be there, just because I want it to be really obvious that we can scroll. And to do that, what I'm going to do is back in here, I'm just going to add this little piece of code. So I've just taken this from the internet with the messages display. Okay, and that will allow me to do that, it will be exactly the same visually, apart from it will always be that now. Great. So let's carry on. I'm actually going to give the message display, let's give this the ID of icon, just so we can pad it out a little bit. So I'm going to grab this and look for essentially any p element that also has the ID of icon. And I'm going to give the padding of this zero from the top and bottom this time and seven pixels from the left and right, just to pad it out from everything else that is going on here. So I've padded that out. Okay, great. Now let's start the input. So once again, all I'm going to do is grab the input element. Okay, so the actual input, there's only one in our project. So I'm just going ahead and grab the whole thing. And essentially, let's kind of start it to look a little bit like a message. I'm going to go ahead and also use box sizing boarder box on the input. Let's give it a boarder of solids. RGBA transparent, and go black, and then 0.16. And make sure there's one pixels in width. Let's pad it out a little bit. So I'm going to be padding 16 pixels and a margin of 2%. Okay, so everything's got a margin of 2%. So that's what it looks like at the moment. Now, if I want this to kind of be centered, right, and fit exactly in the app itself, I'm going to have to use flex box on the app, which we didn't do. So let's go ahead and do that. I'm just going to initialize flex box. And then I'm going to send everything from left to right. And also make sure that everything's on top of each other by adding flex direction column. So that's what it looks like at the moment or fits in the app nicely. And we've got that scroll action going on. And now we also have an input. Let's just round off the edges and finish styling off that input a little bit more. So I'm just going to go border radius, five pixels. And that should be it. And finally, we're nearly done. And we can get to the meatier stuff. Let's also just start these buttons up a little bit. So all I am going to do is just grab the button container. So the class name of button container. Again, I'm just going to give a margin of 2%. I'm going to make sure that the buttons are next to each other. And I'm going to position them at the end by using justify content, flex and okay. And now I'm going to say that any button that lives inside the button container, so that's what I've written just now, I'm going to make sure that the text is upper case. So there we go. I'm going to pad each one out by seven pixels. And I'm also just going to give it a border of none. And now if that button also has the ID of get query, I'm just going to change its color. So I'm going to go with background color, RGB, 255, 9586 to get that red that we used before. And as the border radius, I'm actually going to round off the top left 10 pixels, zero on the top right zero on the bottom right and 10 pixels on the bottom left. And now let's do the same for the clear chat button. Okay, so we're grabbing a button by the ID of clear chat. And now I'm going to swap this round. So we're going to go zero 10 pixels, 10 pixels, zero. And let's make this yellow. So I'm just going to change these to be 18945. Okay, great. And there we have it, there is our app. Now let's get to hooking it up. So for this, let's set off with the back end first. So let's just go ahead and go in here and let's set up our back end. So not the TSX file, the index TS file, that's not going to have any JSX. First off, I'm just going to put in my API key up here, we can of course move it out to an ENV file. But let's just get this working for now. Okay, so that is my API key, just right there. I'm just gonna move that down. Now let's define the port we want to run our back end on, I'm going to say 8000. And this is a number as we are writing in TypeScript. So we're going to have to start working with types. Before we move on, let's just go ahead and check our package JSONs look the same. So yours should look like this. I think we have everything in here that we need. Please go ahead and check this slowly. Okay. And let's not also forget to import the OpenAI package as that is another one that we're going to need. So npm i openai. Great. So let that do its thing. And then it should show up in here, which it has now done. Great. Let's carry on. Next, I'm going to import. So now we're using import express, as well as two types. So application, request, and response from express. So those are two things that we're going to have to do. We're also going to have to import cors from "cors" as well as import two things from OpenAI and as configuration and OpenAI API. Okay, so there we go. Let's go ahead and reorder this to the top. So just like that. And I believe we need to also import the type cors. So let's go ahead and do that npm i save dev type cors. So once again, let's just get up our terminal and do npm i save dev type cors. Okay, so then we can work with course in TypeScript. And there we go. So if we now look in here, I'm just going to show you where that has gone. That's gone all the way down there. Great. Okay, so now it's actually you get to using express, I'm going to grab express, which is imported and call it to release all of its wonderfulness. And let's say that as the const app. And this is where we use the application type that we just imported from express. So we've got that now express now lives under the const app, which means that I can get up and use and pass course through and call it so that we don't get any cause error messages. I'm going to do the same for working with JSON. So I'm going to get express and call JSON. So there we go, we can now work with passing JSON from the front end to the back end in this project. Great. Now from OpenAI, I'm going to essentially use these in order for us to communicate with OpenAI. But first we need to pass through our API key. So I'm going to create a new configuration, pass through an object that simply can have our API key. And we're just going to literally pass through our API key. And let's save this as const configuration, just like that. So you can use it later on. Now I'm going to essentially create a new OpenAI API, and just pass through that configuration to just pass it through into here. And save this, you can save it as whatever you want, I'm going to save it as OpenAI, so that we can use it later on. So great, we should now be authenticated. Let's get to writing our route to an endpoint. First off, I'm going to listen out to any changes. So I'm going to pass report report is 8000. I'm going to put a callback function that's just going to console log out. Your server is running on port, and then the port. Okay, so that's all I'm going to do. So now let's write that route, it's going to be a post request, as we have been working with. And then I'm just going to, let's make an endpoint, let's just go ahead and make one up, you can call this whatever you want, essentially now who is it localhost 8004 slash completions, then we're going to want to do something. And that is an async function, I'm going to pass through the request and the response. And then these have types that we did import from Express. So that's the request type and the response type. And now I'm going to try something and catch any errors, so catch error. And if there are any errors, I'm just going to console error, the error, I'm also going to send something over. So rest status 500 error for error and just send the text of server error. Okay, you don't have to but that is what I have done. Great. So what do we want to try? Well, we're going to await the OpenAI, create completion, or create chat completion to be precise. Let's save this as const completion. And I'm going to pass through whatever we want to send to OpenAI. And that is the model that we want to use. In this case is GPT for and then the messages that we want to pass through as part of the chat. So the message is should look like this, you need to put an array, and each message is symbolized by this little object right here and you savvy role. So it's going to be the user so us, and then whatever we pass through, we're going to be passing this through from the front end, though, I'm going to pass that through the body as a message. So I'm just going to go ahead and do request body message. And because I want to only bring back stuff as SQL requests, or even if we type, name my dog, I'm actually going to append some text here that says create a SQL request to and then whatever we pass through, okay, so everything will be turned into an SQL request. So that is a little cool hack for you to essentially change every single request that we send, but on the back end. Okay, great. And that should be part of the content. So I'm just going to put this maybe on a new line, so it's easier to read for you. Okay, so that's my array. And here is one message that we're going to be sending over. And that's really it. So once we have the messages, so that's the whole object we are passing through, we're just going to send back whatever comes back as the completion. We're going to go into the data, we're going to get the choices. We're going to go into that array, get the first thing to come back and get its message. So that is just the format of the data coming back to us from the AI. I'm going to show you what this looks like as well. But first, let's get to hooking this up to the front end. So now here, let's just go ahead and make something happen on click of this. So on click, I'm just going to get query. And let's define our function get query. So cons, get query. And then I'm just going to define up here, I'm going to try something and catch any errors. So just like we did previously, match error, console, error, the error. And what shall we try? Well, we're going to actually use the fetch API from JavaScript. And we're going to fetch from HTTP, local host, 8000. So our back end that we just created for slash completion. So the endpoint that we just wrote. And of course, this is a POST request. So we're going to pass through some options. So let's define those options. We can do so here, const options equals. And then the method we're going to pass you is a POST method, the body. Well, we're going to pass it through JSON string files as an object. And I'm just going to use the message. And let's just maybe hard code something. For now, let's go ahead and create a table. Okay, so we're just hard coding it at the moment. Let's also pass through some headers though. So headers, as we are working with JSON, I'm just going to pass through content, type application. Jason. Okay, so those are all my options that I want to pass through. And this is an async method, which means we need to use the await keyword, which also means that await can't live inside a function can only live in inside async function. So we have the async keyword there. So we're going to wait for the response of this. And let's save this as something I'm just going to go ahead and save it as a response. And then I'm just going to for now, grab the response and get its JSON. So oh, that's also async, which means we need to await it. And once that comes back, let's just save this as data. So before we do much else, I'm just going to console log data just so we can see what's coming back to us. So there we go. Great. So we've now got the bare minimum to get this working. So let's go ahead and try this out. I'm just going to get the console log up to see any errors. So now if I click on the button, get query, we should essentially send this message. So with the request body message to here, right request body message. So once again, this is the whole request. We're getting the body dot notation because there's an object message. And then we're sending that through to the OpenAI API with this appended to the front. And then we should get that message back. So let's go let's click get query. There has been an error. Let's check why. So we have not run our backend. So let your npm run start:backend and hit enter. So the our serve is now running on port 8000. And let's try this again. I'm just going to do that to clear this. So we've clicked on it. We are now waiting for our message to come back. And great, that is the message that comes back. Its role is from the assistant and the content is below is the SQL request to create a table called and then we have the response. Great. So let's go ahead and show that in here, right? So let's go ahead and do that first. So now let's go ahead and go to the app TSX file. And let's use state in order to save to the state of the app. So I'm just going to import use state from react. Use state from react, just like so. And that means I can save this, let's save this chat, const chat, set chat. And I'm going to start off with this being actually an empty array, because we're gonna have to add to that array, I just want to save all the chats that we have. And we know that our chat is going to come back with a role and content, right? So I'm just going to do this again, so we can see. Okay, there's my object, it has a content and a role. So let's go ahead and define that interface up here. I'm going to go into interface, chat, data. So one individual chat is gonna have a role, and that's going to be a string. And then content is also going to be a string. Okay, so I'm just defining the types up here. So that means that I can now use this interface to say that this will only take things in the array that look essentially like this object, because you'll have those types. So that is what I am doing. This is some TypeScript for you chat data. And make sure that's in an array. So only objects that look like this can go into this array now. Great. So now let's set chat. So once we get that back with console log in the data, I actually just want to set the chat, but I also want to not override the array, I want to add to the array. So for tour this, I'm just going to get the previous state, I'm just going to go ahead and call it old chat, we can call it whatever you like, I'm going to get that array, I'm going to spill out the old chat back into it, I'm going to pass through the new data. But along with that, I also actually, so I'm just going to show you what happens, I also want to actually say what we have been typing. So for this, I'm going to also have to say to state the value of a input, because at the moment, we're just hard coding like here, right, I don't want that to happen. So let's go ahead and do const value of the input, we're going to change it with set value, let's do use state. And let's start off with being an empty string. So let's also define this as being a string, this should only be a string ever at all times. So the value, we want we want to actually see that change in the input. So I'm just going to pass through the value. And on a change of the value, I'm going to get the event. And I'm going to use set value to change it to wherever we are typing into the input. So that's how you would do that. Great. So now that means that instead of hard coding this, I could use the value of whatever we typed into the input to override that there. Okay, great. So I'm just going to show you if I console log value down here. So there we go. So I'm just going to type some stuff, and it will change. So that is value, as you can see on AppTSX lambda line 35. So whenever I essentially click to get a query, I get the response back from the assistant. But I also want to say what I've been typing. So I'm going to actually create a new object. I'm going to call this user message, and I'm just going to construct an object that looks exactly the same as the chat response. So when I have a role, and I'm also going to have content for my role, I'm going to hard code as user because it's me. And the content is just going to be the value of what I've sent over. So that is now my user message. And I also want to pass that through into the search chat array. Great. So now if I console log chats, I'm just going to show you what that looks like. Let's just refresh. So we clear that. Create a table for users. Get query. So it's empty at the moment. Our chat is empty. But what do we expect to happen? Well, I expect two objects to come back, one from the API with the role of assistant, and one that I added in the front end, right, with the role of user. And there we go. So indeed, we have the role from the assistant. And the assistant says, well, it's just giving us the text of how to create a table. And then me, I've hard go to user and the content is exactly what I wrote in here. Wonderful. So we're saving all of that. If I was to write another one, then those two more objects should be saved in here. Each time we're saving two objects. So now let's use this data to display it. So all I am going to do is actually go ahead and well, let's filter some of these messages, right? So I'm going to get the chat and I'm going to filter each message. So each object message. And I'm going to say if the message role equals user, then we know the my messages. So let's say this is const filtered user messages, just like so. And I'm just going to pass those filtered messages into the message display. So user messages is going to be the prop, I'm just going to pass your filter to do some messages, which means that now on message display, messages display, sorry, plural, I can pass that through. And as this is typed script, we're going to have to define those props. So interface messages, display props. And well, we can actually also go further and define the user messages interface. So interface, so just defining what the object really looks like user message has a role. That is a string interface. And also content, right? That is a string. So we know that the user message is going to be array of this. So user messages, the prop user messages, right? The prop user messages is going to be a user message, but it's going to be array of them. So that's what I've written there. So hopefully, that makes sense. And now we can just use this to define the props we are passing through. So this will essentially say what types all our props have, we only have one prop. Okay. And it's made up of this, those things in an array. Cool. So now we don't need to hard code this anymore. I'm actually going to get the user messages. Okay. And I'm going to map someone use dot map to map each user message, let's go with singular onto a message display. Cool. We should really have a key here too. So I'm just going to use the index for this just because we don't want any errors showing up. Maybe I'll just put this on a new line. So I'm going to have a key that's essentially the index. And then I'm just going to pass through the message itself as the user message, which means we now need to go to the message display and pass down the message. Okay, so let's do structure the message. The message is easy because we know what it's going to look like, we can essentially just define the message props for this easily. So interface message display props, and the props for this for the message looks like this is an object that has a role. In fact, what we can do is just grab this user message again, paste it up here. And then just use the user message. Okay, we're just defining that even further. interface. Great. So now let's grab those props. And just do that. Wonderful. So this is looking so so good. And now that we have each message, the message that has a role and content, I can grab the message. And I can use Kylie braces and get the messages, roll and display it, and also get the messages content on display. We are getting some Kylie lines here. Why is that? We seem to have missed a parenthesis. And there we go. So if we look in here, now, we get a user and create table for users. Perhaps I don't really want that user showing up. But if you do, you can, I'm just going to come at the output now. And there we go. I'm also just going to add in a text symbol for the icon itself. So here is my text symbol that I have chosen. If you want it to, I'm just going to show you where to get it from. You can essentially get it from here. So there is the URL if you want to get it. Great. So this is looking good. Create a table for users. Create a table for dogs. Don't really know. Let's just go ahead and do that. And that should be added up here. And we are only saving the messages that have the role of user as we filter them out. Wonderful. So that's what I have done. Now this is looking so, so good. The next thing I want to do is just get the last possible content of the message that has the role of assistant to show up here. So let's go ahead and do that. So back on the app itself, I am actually going to filter once more, because I'm going to have to filter out the chat. So I'm going to get the chat to use filter once more to filter out each message. And if the message role this time equals assistant to anything that comes back from OpenAI, I just want to get the very last one. So I'm just going to use pop the method of pop to get the very last one. And that's the latest that we can call it code. So latest code, even though technically it's a string. So once we have the latest thing that's come back to us from the AI, I'm simply going to pass that through. So the text that we're going to use for this is going to be the latest code. And we're not we don't need this role. We just want its content. Okay. So we're going to display that. Or if that doesn't exist, I'm just going to display an empty string. Cool. So now let's pass through the prop text on the code display. So let's get up our code display. And let's pass that through. Okay, so this time we are not passing through the whole object, we're literally just passing you the string that's attached to the content. Right, we're going in here, we're filtering out everything by the role of assistant. So there should only be two items in our array. And then literally just going dot notation content. So I'm passing through the last this one, right? We're passing through the last one that came back to us. So let's define that prop interface code display props text string. Okay, so now we can just use that to define the types of props. Wonderful. And now I could just get that text and display it in here. So there we go. latest code is possibly undefined. That is fine. Let's check if it exists. And then also this needs to be content. Great. So that should show up. However, I feel that we haven't changed the text of this. So let's just change the color of this text. So on the code display, let's actually get the code output as well. Where was the code related stuff, code display, I'm also just going to grab the code output, let's give it a margin of 20 pixels. And I'm also going to say that any P element that is inside the code output is going to have a different text color. And I'm just going to make it the yellow that we have been using. So 25518945. Great. So there we go. That is now showing up. We've nearly done it. The last thing we do is just clear the chat. So let's write a function for that. So let's go ahead and do that here. On click is going to be super easy. I'm just going to clear chat. And let's define that up here. Const clear chat. All I'm going to do is set the value to be an empty string again. So let's just put that in here and pass through an empty string. And I'm going to set the chat to be an empty area again, so we can start fresh. So let's check that out. Let's do this here. Let's get that query. And that should be saved up there as part of our history. Okay, that is wonderful. And we also get the query to do this. Let's do create a table called users and get that query. So once again, that should do its thing. And there we go. Let's go ahead and do a few more update the table to have phone numbers. Okay, so that hasn't done it. But it's given us some instructions and add a fake user to the table users. And there we go. And it's shown us how we can, of course, scroll through all of this. And if I click on clear chat, that has cleared our chat for us. Great. One final thing we're going to do, just to make sure that everything is safe, is just create a dot in the file. So we can keep our API key safe. So let's add that in here. Let's do API key equals, and let's get it from the back end. So index TS, there we go. I'm just going to grab this, it is a string. So that is implied. And when you process env to look in that dotenv file and get the API key. So that's what we have done. And then in the API key here, I'm just going to save that in here like so. So we're done with this. And we're just going to have to import the dotenv package. Okay. So once again, I'm just going to get on my terminal and do npm i dotenv, just like so. Okay. And great. And finally, we just need to import that up here. So import, like so. And then let's get dotenv and get config and call it. Okay, in order to use it. And great, that's it. I hope you've learned a lot. I really enjoyed showing you how to do this in TypeScript. So I hope you had fun. And I hope to see you again soon. Phew. So by the end of this course, you would have learned how to create completions using the text completion endpoint, create chats using the chat completion endpoint, and create images from prompts, as well as already existing images, thanks to the DALL-E model as well. So this really has been a lot. Hopefully you've managed to get through some of the projects too. And if you didn't, don't worry, you can always come back to this course whenever if you wish. If you did enjoy this course, I would like to contribute to freeCodeCamp as a thank you, please do check out the video description below. Okay, everyone, and that is it. Thank you so much for watching along with me. I hope you've learned something useful. And I hope you enjoy using the OpenAI API.
Info
Channel: freeCodeCamp.org
Views: 516,516
Rating: undefined out of 5
Keywords:
Id: uRQH2CFvedY
Channel Id: undefined
Length: 317min 49sec (19069 seconds)
Published: Wed Apr 19 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.