1 00:00:00,000 --> 00:00:09,424 [MUSIC] 2 00:00:09,424 --> 00:00:10,080 Hey, what's up? 3 00:00:10,080 --> 00:00:12,979 My name's Dustin and I'm a developer here at Treehouse. 4 00:00:12,979 --> 00:00:16,484 Today we're gonna build out a very basic version of ChatGPT. 5 00:00:16,484 --> 00:00:20,828 And we're gonna do this with just HTML, CSS, and vanilla JavaScript. 6 00:00:20,828 --> 00:00:25,067 So what we'll do is we'll start off with the HTML first to build out our UI and 7 00:00:25,067 --> 00:00:26,339 it'll be very basic. 8 00:00:26,339 --> 00:00:29,923 And then I'm just gonna touch very briefly on the CSS. 9 00:00:29,923 --> 00:00:33,035 Because the meat and potatoes of this project is gonna be the JavaScript, 10 00:00:33,035 --> 00:00:34,402 I wanna focus more time on that. 11 00:00:34,402 --> 00:00:37,008 So in the description or teacher's notes down below, 12 00:00:37,008 --> 00:00:39,000 there's gonna be a link to a GitHub gist. 13 00:00:39,000 --> 00:00:42,555 And you can go there to copy all the CSS for this project or download the file and 14 00:00:42,555 --> 00:00:44,210 include it in your project folder. 15 00:00:44,210 --> 00:00:46,340 Whatever you wanna do is completely up to you. 16 00:00:46,340 --> 00:00:50,082 You can even create your own styles and make this project your own. 17 00:00:50,082 --> 00:00:53,201 But what we'll do is spend the majority of the time writing the JavaScript out. 18 00:00:53,201 --> 00:00:57,981 So if you wanna follow along, feel free to open up your favorite text editors, and 19 00:00:57,981 --> 00:00:59,246 let's get started. 20 00:00:59,246 --> 00:01:03,090 All right, so let's get started by looking at the project's file structure. 21 00:01:03,090 --> 00:01:07,836 So first, we have just an index.html file with some boilerplate code, and 22 00:01:07,836 --> 00:01:13,252 we're linking the CSS stylesheet, and then we're also linking the JavaScript file. 23 00:01:13,252 --> 00:01:15,694 Next, we have the CSS file, and just remember, 24 00:01:15,694 --> 00:01:19,210 grab the code snippet from the GitHub gist link below for the styles and 25 00:01:19,210 --> 00:01:21,490 include them in the project to follow along. 26 00:01:21,490 --> 00:01:23,375 Or you can just write your own styles and 27 00:01:23,375 --> 00:01:25,560 make this project look the way that you want. 28 00:01:25,560 --> 00:01:28,016 Next, we have an empty index.js file and 29 00:01:28,016 --> 00:01:30,622 this is where we'll write all of our logic. 30 00:01:30,622 --> 00:01:34,430 Lastly, we have a folder for images where I've got a ChatGPT logo. 31 00:01:34,430 --> 00:01:37,097 Feel free to grab one off the internet if you want, but 32 00:01:37,097 --> 00:01:39,780 you don't need one to follow along with the project. 33 00:01:39,780 --> 00:01:42,755 All right, so let's get started with the markup. 34 00:01:42,755 --> 00:01:46,560 We can get started by creating a container for our entire project. 35 00:01:46,560 --> 00:01:49,000 This will be a div with the class of chat container. 36 00:01:49,000 --> 00:01:52,955 And next, we'll just have two children elements within the chat container, and 37 00:01:52,955 --> 00:01:56,530 one will be for the chatlog, and the other one will be for the new message. 38 00:01:56,530 --> 00:02:00,256 The chatlog container will hold our message prompt as well as the AI's 39 00:02:00,256 --> 00:02:04,614 response while the new message container will hold our form to send the new message 40 00:02:04,614 --> 00:02:05,263 to the API. 41 00:02:05,263 --> 00:02:09,550 So while we're inside of the new message container, let's set that up now. 42 00:02:09,550 --> 00:02:14,018 We can just create a form and inside of the form, we'll just have an input. 43 00:02:14,018 --> 00:02:18,281 And we'll give that input a type of text and ID of prompt and 44 00:02:18,281 --> 00:02:20,722 a placeholder of send a message. 45 00:02:20,722 --> 00:02:25,864 Cool, okay, so, let's open this up in the browser and see what it's looking like. 46 00:02:25,864 --> 00:02:26,701 Awesome, cool. 47 00:02:26,701 --> 00:02:29,740 We see our input at the bottom and an empty chatlog. 48 00:02:29,740 --> 00:02:33,109 So let's get started with the chatlog markup now. 49 00:02:33,109 --> 00:02:36,734 Even though all of this will be rendered dynamically with the JavaScript later on, 50 00:02:36,734 --> 00:02:39,290 it's still good to see how this is gonna look statically. 51 00:02:39,290 --> 00:02:44,168 So each message instance will contain my message prompt as well as 52 00:02:44,168 --> 00:02:45,770 the AI's response. 53 00:02:45,770 --> 00:02:50,500 So let's create a container with the class of message instance container. 54 00:02:50,500 --> 00:02:53,930 Each message will have a class of message. 55 00:02:53,930 --> 00:02:57,891 So let's create two divs here with the class of message, but 56 00:02:57,891 --> 00:03:02,782 one will get a class of user message, which is gonna be our message prompt, 57 00:03:02,782 --> 00:03:05,826 while the other one gets a class of AI message. 58 00:03:05,826 --> 00:03:08,480 The markup for each of these messages will be pretty similar. 59 00:03:08,480 --> 00:03:12,183 So let's toggle both of them and create a content div. 60 00:03:12,183 --> 00:03:16,813 And inside of this content div, we'll just have a div with the class of 61 00:03:16,813 --> 00:03:21,225 message image and this is where our image for each message will go. 62 00:03:21,225 --> 00:03:25,420 You can choose to add your own image for your user but in our example, 63 00:03:25,420 --> 00:03:27,120 it's just gonna be blank. 64 00:03:27,120 --> 00:03:31,542 So we'll leave this div empty and next, we'll just create a paragraph tag and 65 00:03:31,542 --> 00:03:34,024 I'll write this is a message from the user. 66 00:03:34,024 --> 00:03:35,785 And for the AI message, 67 00:03:35,785 --> 00:03:40,640 we'll obviously want to make it say this is a message from the AI. 68 00:03:40,640 --> 00:03:44,761 Also inside of the message image for the AI message, 69 00:03:44,761 --> 00:03:48,894 I'm going to link up our image for our ChatGPT logo. 70 00:03:48,894 --> 00:03:51,754 Awesome, so that's all the markup that we're gonna need for 71 00:03:51,754 --> 00:03:54,730 our message instance and sweet, we see two separate messages. 72 00:03:54,730 --> 00:03:59,721 I do wanna change one thing I'm going to change this is a message from the AI 73 00:03:59,721 --> 00:04:00,695 to thinking. 74 00:04:00,695 --> 00:04:04,301 And I'm also going to give a class of thinking to the paragraph tag that's 75 00:04:04,301 --> 00:04:05,940 associated with the AI message. 76 00:04:05,940 --> 00:04:11,830 And what this is gonna do is add a pulsing animation to the paragraph text for 77 00:04:11,830 --> 00:04:13,150 the AI message. 78 00:04:13,150 --> 00:04:18,352 And we'll remove this later on whenever the response comes back from the API. 79 00:04:18,352 --> 00:04:22,075 Okay, great, so we're actually done with all of the markup that we'll need and 80 00:04:22,075 --> 00:04:25,692 we'll come back later to remove the message instance container markup once we 81 00:04:25,692 --> 00:04:27,580 render that part of the UI dynamically. 82 00:04:27,580 --> 00:04:32,000 So let's get started with the meat and potatoes of this project, the JavaScript. 83 00:04:32,000 --> 00:04:36,716 So in order to connect to the OpenAI API, we'll just need a couple of things first. 84 00:04:36,716 --> 00:04:39,950 The API key and the API URL. 85 00:04:39,950 --> 00:04:41,717 The URL will be 86 00:04:41,717 --> 00:04:49,535 https://api.openai.com/v1/chat/completi- ons. 87 00:04:49,535 --> 00:04:51,112 Now, in order to get an API key, 88 00:04:51,112 --> 00:04:53,750 you'll just need to create a free account on OpenAI. 89 00:04:53,750 --> 00:04:56,550 It's pretty quick and I'll show you how to do it. 90 00:04:56,550 --> 00:05:01,350 Just head on over to platform.openai.com and sign up. 91 00:05:01,350 --> 00:05:04,873 Once you have your account, just click on the account icon and 92 00:05:04,873 --> 00:05:06,580 then go down to view API keys. 93 00:05:06,580 --> 00:05:10,140 Once you're there, just hit Create a new secret key and 94 00:05:10,140 --> 00:05:14,550 give it a name like chatgpt clone, and then click create secret key. 95 00:05:14,550 --> 00:05:19,282 Once you have your API key, click the copy button., and I already have a key so 96 00:05:19,282 --> 00:05:21,162 I'm just gonna paste mine in. 97 00:05:21,162 --> 00:05:24,803 Please do not waste your time trying to copy my key it won't work for you and 98 00:05:24,803 --> 00:05:27,879 I'm gonna be deleting this key after this video is recorded. 99 00:05:27,879 --> 00:05:30,354 Also, do not share your key with anyone or 100 00:05:30,354 --> 00:05:33,760 host this repo on GitHub without making your key secure. 101 00:05:33,760 --> 00:05:37,668 I'll link some resources down below on how you can use environment variables to keep 102 00:05:37,668 --> 00:05:38,340 this secure. 103 00:05:38,340 --> 00:05:41,370 Okay, so now let's set up some variables that I know we're gonna need. 104 00:05:41,370 --> 00:05:46,574 I'll write const form and that's gonna equal document.querySelector and 105 00:05:46,574 --> 00:05:51,552 we're gonna target the form, then I'll just write const promptInput. 106 00:05:51,552 --> 00:05:54,190 And this will equal document.querySelector. 107 00:05:54,190 --> 00:05:57,693 And we're looking for the ID prompt. 108 00:05:57,693 --> 00:06:01,890 And then we'll just write const chatLog = document .querySelector and 109 00:06:01,890 --> 00:06:04,540 we're gonna look for the class of chat-log. 110 00:06:04,540 --> 00:06:09,960 Okay, so you know how when you set up a form and click enter the page refreshes? 111 00:06:09,960 --> 00:06:13,397 Well we don't want that, so that's the default behavior. 112 00:06:13,397 --> 00:06:17,295 And the easiest way to remove that is to set up a submit event listener on 113 00:06:17,295 --> 00:06:19,739 the form, taking the event parameter, and 114 00:06:19,739 --> 00:06:22,860 then just call the prevent default method on the event. 115 00:06:22,860 --> 00:06:25,441 And now when we click Enter in the browser, 116 00:06:25,441 --> 00:06:27,602 our form does not refresh the page. 117 00:06:27,602 --> 00:06:31,520 Okay, so now let's figure out what we wanna do when we do click Enter. 118 00:06:31,520 --> 00:06:33,930 Well, let's make sure that our input isn't empty. 119 00:06:33,930 --> 00:06:37,576 So let's first set up a variable named value and 120 00:06:37,576 --> 00:06:40,592 let it equal our promptInput.value. 121 00:06:40,592 --> 00:06:43,263 And if value is not equal to an empty string, 122 00:06:43,263 --> 00:06:46,090 we'll want to create a new message instance. 123 00:06:46,090 --> 00:06:48,390 So let's write a function call for 124 00:06:48,390 --> 00:06:53,003 a function that we'll set up later called createMessageInstance. 125 00:06:53,003 --> 00:06:57,700 And we'll basically want to ask ChatGPT our question based off of the prompt. 126 00:06:57,700 --> 00:07:03,624 So we'll also create a function later, and we can call it now, called askChatGPT. 127 00:07:03,624 --> 00:07:07,896 And lastly, I'll wanna make sure that every time we update our chatlog UI, 128 00:07:07,896 --> 00:07:10,234 it automatically scrolls to the bottom so 129 00:07:10,234 --> 00:07:13,000 that our most recent message is always visible. 130 00:07:13,000 --> 00:07:16,745 So we'll create a function later called handleScroll, 131 00:07:16,745 --> 00:07:18,780 and we'll call that now also. 132 00:07:18,780 --> 00:07:22,719 And one last thing, we'll also just wanna make sure our input is empty so 133 00:07:22,719 --> 00:07:25,054 that we can type a new message again later. 134 00:07:25,054 --> 00:07:26,922 Awesome, I think when we click Enter, 135 00:07:26,922 --> 00:07:29,311 every function that we wanna run is being called. 136 00:07:29,311 --> 00:07:30,950 So let's set up those functions now. 137 00:07:30,950 --> 00:07:34,564 I'll create a function for createMessageInstance, 138 00:07:34,564 --> 00:07:39,760 I'll create another one for askChatGPT, and one last one for handleScroll. 139 00:07:39,760 --> 00:07:42,735 Okay, so let's knock out the quick and easy one first, 140 00:07:42,735 --> 00:07:44,776 which is the handleScroll function. 141 00:07:44,776 --> 00:07:46,596 Since the name is a little vague, 142 00:07:46,596 --> 00:07:50,050 I'll add a comment that says scroll the chatlog to the bottom. 143 00:07:50,050 --> 00:07:54,934 And all we'll wanna do in here is just set the chatlog's scrollTop property 144 00:07:54,934 --> 00:07:57,540 to the chatlog's scrollHeight value. 145 00:07:57,540 --> 00:07:58,841 And that's it. 146 00:07:58,841 --> 00:08:02,600 So we can call this function anytime that we wanna make sure we scroll to the bottom 147 00:08:02,600 --> 00:08:03,890 of our chatlog container. 148 00:08:03,890 --> 00:08:07,250 Now let's work on the CreateMessageInstance function. 149 00:08:07,250 --> 00:08:09,970 To create our message we'll need our prompt. 150 00:08:09,970 --> 00:08:14,175 Luckily, we are setting the value of our input to this value variable. 151 00:08:14,175 --> 00:08:15,688 So when we call our function, 152 00:08:15,688 --> 00:08:18,420 we can use that as the parameter in the function call. 153 00:08:18,420 --> 00:08:22,551 So now in the function declaration, let's pass in an argument for this. 154 00:08:22,551 --> 00:08:23,830 We can just call it prompt. 155 00:08:23,830 --> 00:08:28,400 And for now, let's just console.log prompt to see if everything's working correctly. 156 00:08:28,400 --> 00:08:32,971 So I'll hit Save, and in the input field I'll just type in hello world and 157 00:08:32,971 --> 00:08:33,727 hit Enter. 158 00:08:33,727 --> 00:08:37,441 And whenever I click inspect and then navigate to the console, 159 00:08:37,441 --> 00:08:39,480 we see hello world in the console. 160 00:08:39,480 --> 00:08:40,707 Awesome. 161 00:08:40,707 --> 00:08:43,740 So let's go ahead and remove that console.log statement. 162 00:08:43,740 --> 00:08:48,049 And what do we wanna do inside of this createMessageInstance? 163 00:08:48,049 --> 00:08:52,940 Well, we'll basically just want to replace the inner HTML of our chatlog container. 164 00:08:52,940 --> 00:08:58,032 So, I'll write chatlog.InnerHTML += and we'll use a set of backticks so 165 00:08:58,032 --> 00:09:01,100 that we can interpolate our prompt argument. 166 00:09:01,100 --> 00:09:06,707 So back in the HTML, let's find our instance of our new chat message, 167 00:09:06,707 --> 00:09:10,520 and we'll just copy that entire chunk of HTML. 168 00:09:10,520 --> 00:09:14,804 I'll hop back into my JavaScript file, I'll paste it inside of the backticks, 169 00:09:14,804 --> 00:09:17,450 and I'll fix up my indentation just a little bit. 170 00:09:17,450 --> 00:09:20,835 And inside of our user message paragraph tag, I'll just copy that entire paragraph 171 00:09:20,835 --> 00:09:23,610 tag, I'll remove the text that says this is a message from the user. 172 00:09:23,610 --> 00:09:27,220 And I'll replace it with a dollar sign and a set of curly braces. 173 00:09:27,220 --> 00:09:30,742 And now we can just paste in our prompt argument. 174 00:09:30,742 --> 00:09:32,400 So I'll hit Save on this. 175 00:09:32,400 --> 00:09:37,170 And what we can do now is hop back into the HTML file, and we'll remove the chunk 176 00:09:37,170 --> 00:09:41,146 of HTML that we wrote and we'll just replace it with a comment that 177 00:09:41,146 --> 00:09:46,025 says something like dynamic so that we know that this is dynamically rendered. 178 00:09:46,025 --> 00:09:49,306 I'll hit Save and I'll come into the browser and 179 00:09:49,306 --> 00:09:52,437 I'll just write hello world and press Enter. 180 00:09:52,437 --> 00:09:56,862 And now we have a new chat instance where you see my message on the top and 181 00:09:56,862 --> 00:10:00,393 then what appears to be ChatGPT thinking of a response. 182 00:10:00,393 --> 00:10:04,440 And that is all that we will need our createMessageInstance function to do. 183 00:10:04,440 --> 00:10:10,046 So now we need to take our prompt and ping the API with it to get back a response, 184 00:10:10,046 --> 00:10:13,434 or in other words, ask ChatGPT our question. 185 00:10:13,434 --> 00:10:17,603 So now let's work on our askChatGPT function. 186 00:10:17,603 --> 00:10:20,773 In here, we'll just want to make a fetch call to the URL and 187 00:10:20,773 --> 00:10:22,794 we'll want to pass in some options. 188 00:10:22,794 --> 00:10:24,650 The method will be post. 189 00:10:24,650 --> 00:10:28,536 And for the headers, we'll want content type, and 190 00:10:28,536 --> 00:10:31,993 that'll be equal to the application/json. 191 00:10:31,993 --> 00:10:33,903 Then we'll want authorization. 192 00:10:33,903 --> 00:10:38,796 And this is where we'll use our API key, so make sure to use a set of backticks for 193 00:10:38,796 --> 00:10:39,537 the value. 194 00:10:39,537 --> 00:10:43,601 Interpolate the API variable that we set up earlier and 195 00:10:43,601 --> 00:10:46,880 make sure you also add Bearer in front of it. 196 00:10:46,880 --> 00:10:51,710 And now for the body of our request, we'll specify the model and for 197 00:10:51,710 --> 00:10:55,630 this project, we'll use chatgpt-3.5-turbo. 198 00:10:55,630 --> 00:10:58,384 And depending on when you're watching this video, 199 00:10:58,384 --> 00:11:00,834 there may even be a more advanced model to use. 200 00:11:00,834 --> 00:11:02,461 Next, we will supply the message. 201 00:11:02,461 --> 00:11:06,035 This will be an array and inside will house an object for our message. 202 00:11:06,035 --> 00:11:10,143 The role will be set to user since this is our message to the AI, and 203 00:11:10,143 --> 00:11:12,700 the content will be equal to our prompt. 204 00:11:12,700 --> 00:11:16,750 So let's not forget to add prompt as an argument in our function declaration. 205 00:11:16,750 --> 00:11:20,974 And we'll also want to use our value variable as the function parameter when 206 00:11:20,974 --> 00:11:22,303 calling the function. 207 00:11:22,303 --> 00:11:26,175 And finally, we can just take our prompt argument and use it for 208 00:11:26,175 --> 00:11:27,650 our content's value. 209 00:11:27,650 --> 00:11:31,534 So one other thing that I wanna do is set the max tokens. 210 00:11:31,534 --> 00:11:35,850 And basically what this is, is how long of a response that you want from the AI. 211 00:11:35,850 --> 00:11:40,658 You can do something like 100 or even 200, and this will keep it somewhat short. 212 00:11:40,658 --> 00:11:42,290 I'll stick with 200. 213 00:11:42,290 --> 00:11:47,693 So I am noticing some sort of syntax error and I'm not sure, 214 00:11:47,693 --> 00:11:52,010 okay, so I just forgot to add the colon after body. 215 00:11:52,010 --> 00:11:56,379 So for the body object, I'll just go ahead and add a colon. 216 00:11:56,379 --> 00:11:57,760 And that should fix it up. 217 00:11:57,760 --> 00:12:02,348 I'm actually glad we forgot the colon because this reminds me that we also need 218 00:12:02,348 --> 00:12:05,000 to run JSON.stringify on the request body. 219 00:12:05,000 --> 00:12:09,485 So I will go ahead and cut out the contents of the body object, and 220 00:12:09,485 --> 00:12:13,392 then I'll just write JSON.stringify as a method, and 221 00:12:13,392 --> 00:12:16,820 then I'll just paste that back inside, sweet. 222 00:12:16,820 --> 00:12:22,676 Okay, so since fetch is promise based, we can chain a .then method on this. 223 00:12:22,676 --> 00:12:26,139 So let's do that, and we can take the response and 224 00:12:26,139 --> 00:12:29,200 run res.json to get it back in JSON format. 225 00:12:29,200 --> 00:12:31,148 Then we'll get back some data. 226 00:12:31,148 --> 00:12:34,970 And this will have all the information we get back from the response. 227 00:12:34,970 --> 00:12:36,455 So let's write data, 228 00:12:36,455 --> 00:12:41,000 and we'll want to use this data to update our AI's message in the UI. 229 00:12:41,000 --> 00:12:43,830 So let's write a function call for 230 00:12:43,830 --> 00:12:49,206 a function called updateMessage and pass data in as a parameter. 231 00:12:49,206 --> 00:12:50,930 Now we need to go and create this function. 232 00:12:50,930 --> 00:12:53,912 So I'll create a function named updateMessage and 233 00:12:53,912 --> 00:12:56,138 I'll pass in message as an argument. 234 00:12:56,138 --> 00:12:58,810 This will be the data that we get back from our response. 235 00:12:58,810 --> 00:13:01,959 So what do we wanna do with this function? 236 00:13:01,959 --> 00:13:06,350 Well, let's first grab a reference to the paragraph tag with the thinking class. 237 00:13:06,350 --> 00:13:10,702 We'll wanna update the text content of that paragraph tag with the response from 238 00:13:10,702 --> 00:13:11,222 the API. 239 00:13:11,222 --> 00:13:14,420 But what kind of info did we even get back from the API? 240 00:13:14,420 --> 00:13:19,522 Let's console.log message and see what we get back in the console. 241 00:13:19,522 --> 00:13:24,099 I'll hit Save and I'll type in what is JavaScript in the prompt and 242 00:13:24,099 --> 00:13:28,445 after some time, we see the data sent back to us in the console. 243 00:13:28,445 --> 00:13:31,140 If we examine it, we get back an array named choices. 244 00:13:31,140 --> 00:13:35,219 And in the first index of this array, we see an object called message. 245 00:13:35,219 --> 00:13:38,727 And the content property of this object holds our response. 246 00:13:38,727 --> 00:13:43,699 So back in the JavaScript, we can just write our paragraph 247 00:13:43,699 --> 00:13:47,456 tag.textContent = message.choices and 248 00:13:47,456 --> 00:13:52,340 the first index of that which is 0.message.content. 249 00:13:52,340 --> 00:13:56,188 This should handle updating the AI's message with the response that 250 00:13:56,188 --> 00:13:56,927 we get back. 251 00:13:56,927 --> 00:14:00,349 So the only thing we need to do now is remove the thinking class from 252 00:14:00,349 --> 00:14:01,416 the paragraph tag. 253 00:14:01,416 --> 00:14:05,952 And then also I wanna call our handleScroll function just to make sure 254 00:14:05,952 --> 00:14:09,482 we're scrolling to the bottom of our chatlog again. 255 00:14:09,482 --> 00:14:15,360 I'll hit Save and in the browser, I'll type in, what is JavaScript? 256 00:14:15,360 --> 00:14:19,251 And after some time we see the AI's message update. 257 00:14:19,251 --> 00:14:22,320 And we see our response from ChatGPT, perfect. 258 00:14:22,320 --> 00:14:27,461 So if I go and I type in what is Python, we'll wait a little bit longer and 259 00:14:27,461 --> 00:14:31,509 we'll get another response back and sweet, it works. 260 00:14:31,509 --> 00:14:32,330 Awesome, we're finished. 261 00:14:32,330 --> 00:14:37,186 So we built out a very basic version of ChatGPT that lives in the browser and 262 00:14:37,186 --> 00:14:40,571 we only used HTML, CSS, and vanilla JavaScript. 263 00:14:40,571 --> 00:14:43,254 It's not hard to build some pretty complex things with some basic 264 00:14:43,254 --> 00:14:44,290 fundamental concepts. 265 00:14:44,290 --> 00:14:47,828 One thing that I really like about this project is that it's set up to where we 266 00:14:47,828 --> 00:14:49,666 can add as many features as we'd like. 267 00:14:49,666 --> 00:14:53,554 The real ChatGPT has a panel on the left side that allows you to see your chat 268 00:14:53,554 --> 00:14:57,583 history, and that's not hard to implement, and I encourage you to try it. 269 00:14:57,583 --> 00:15:01,311 Another thing that we didn't do that we could add in that would be super simple is 270 00:15:01,311 --> 00:15:02,380 to handle our errors. 271 00:15:02,380 --> 00:15:05,029 So if there's an error that comes back from the API, 272 00:15:05,029 --> 00:15:06,905 how will we show that to the end user? 273 00:15:06,905 --> 00:15:10,073 These are some pretty cool features and they're not hard to implement and 274 00:15:10,073 --> 00:15:12,593 I hope that you build out a really cool version of ChatGPT. 275 00:15:12,593 --> 00:15:15,894 I also hope that this guide helped and you were able to follow along with me. 276 00:15:15,894 --> 00:15:18,320 So until next time, have fun and happy coding.