DALL-E 2 API in JAVASCRIPT for BEGINNERS (OpenAI, Next 13) β
OpenAIVintageπ
2023-04-04
Integration Flow β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INTEGRATION ARCHITECTURE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β USER REQUEST β
β β β
β βΌ β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β β βββββΊ β β βββββΊ β β β
β β OpenAI β β API β β Output β β
β β β βββββ β β βββββ β β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β β β β
β β β β β
β ββββββββββββββββββββββββββ΄ββββββββββββββββββββββββ β
β β β
β βΌ β
β βββββββββββββ β
β β RESULT β β
β βββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββIntegration Points β
- API authentication
- Request handling
- Error management
Transcript β
[00:00] hello and welcome back in today's video I will show you how to build your own AI image generator using doll E2 and next JS our application will allow the user to enter a prompt for example a puppy smelling a flower we can then click on generate and after a few seconds we'll get an image back from doll E2 however we can improve the prompt by adding certain keywords as an example it's always a good idea to add details with regards to the lighting the environment the color scheme Point of View
[00:32] background Etc so in order to assist the user with the keywords we'll provide a list of all the common keywords and clicking any of these keywords will add them to the prompt if we click generate now the result will look drastically different as you can see here this tutorial is beginner friendly and you only need very basic knowledge of JavaScript to follow along if you get stuck at any point during this tutorial you will find a link to the GitHub repo in the description of this video As for the prerequisites you will need node.js
[01:04] installed you can install that by going to nodejs.org and install the LTS version of node you will also need a code Editor to follow along in this tutorial I will be using visual studio code as for the framework we'll be using nextjs which will allow us to both the front end for the application using react as well as the back end logic required for calling openai apis for starting the application we'll be using Tailwinds CSS alright let's get started
[01:34] open up a new folder for your project if you are using vs code I recommend installing the following extensions this es7 plus extension will help us with syntax highlighting for the react part of our project Palvin CSS will give us Auto completion when installing the application we can set up a new nextgis project by opening up the terminal and running the following command npx create next app at latest we can then give the project a name if you enter a name here
[02:04] it will create a subfolder in this root directory alternatively you can just press period and enter would you like to use typescript this is up to you but for me I'll just say no would you like to use eslint I will say no would you like to use the source directory I will say no would you like to use the experimental app directory for this I'll say yes import aliases just press enter after setup is complete we need to install one more package that will allow us to use openai's Library so in the terminal press npm install open AI we
[02:38] can now test if our next GIS project is working by running the following command npm run Dev you should be able to access your project by going to localhost 3000 after opening the application we can see that next JS template loading up if you would like more information on how to set up next.js projects I have a series on my channel that goes through the fun the main tools of nexjs I will link it in the description of this video and you should see a card popping up right now first let's clean up our project and
[03:08] remove anything that we don't need in the app directory we can remove this page.module.css file we can also open up page.js and make a few changes here or remove all of these Imports I will also remove this font definition we can then also remove everything in the return statement from the opening main tag all the way down to the closing main tag and for the time being what I'll do is I'll add back the main tag with some text like hello world after saving this will see the changes reflecting on the
[03:39] page let's also change this globals.css file I'll actually go ahead and remove all of The Styling in this file what we'll do instead is we'll replace the styling with Tailwind CSS so let's go ahead and set up the element in our project first we need to stop our development server by pressing Ctrl and c and then in the terminal we need to install a few dependencies for setting up Tailwind in your project I recommend using the talwin documentation so on Tailwind simply click on get started
[04:09] framework guides next JS we can then follow along from step two so I'll simply copy these two commands then back in our terminal or paste in those commands and press enter after the tell when dependencies have been installed we need to add this to the talent config file so I'll just copy all of this we can then go to the Tailwind content file remove all of this and paste in this content we can then save this file we then need to paste these three lines in the global.css file so I'll just copy
[04:40] these we can go back to the globals.css file and paste in those lines and save we now need to run our Dev server by running npm run Dev let's get started with our app the first thing I would like to do is both the backend API which will communicate with open AI after installing next.js next actually gave us an example backend API we can find it by going to the API folder hello and route.js in this route file we can
[05:11] specify different methods for the API like get post Etc in this example we have a get method that we can use and all this get method does is it returns a response with a text hello nextjs we can test out this endpoint by going to localize 3000 slash API slash hello you do not need to specify the route file after pressing enter we get this response back hello nextjs for our application I want to
[05:41] change the route folder from help to something else I'll just rename hello to open AI I'll also change the get method to a post instead so in order to communicate with openai we need to import a few things from the openai package so from openai we will import configuration as well as open AI API we then need to instantiate a new configuration object we then need to instantiate a new configuration object by calling new configuration the configuration class takes in an object
[06:13] as a parameter and we only need to specify one parameter to make this work called API key we can get this API Key by logging into our openai account so what I need you to do is go to platform.openai.com and create a new account after logging into your account you should see a page like this click on personal and then click on view API Keys then click on create new secret key copy this key and then go back to your project in our project we will create an
[06:43] environment variable file to store these values so in the root of our project create a new file called dot env.local create a new variable called openai API key and paste in the key value go ahead and save this file and close it in order for the environment variables to become available to the project we need to restart the dev server so I'll do that by pressing Ctrl and c and then running npm run Dev again we can now provide that we can now provide that openai key as this value we
[07:16] can do that by entering process.env dot open AI API key now that we have the configuration object we can now create an instance of the openai library by creating a new variable called openai and then creating a new instance of openai API and then passing in the configuration object that we created up here we are now able to interface with the functions made available by the open AI library for example if I call openai we can see this autocomplete coming up with a whole
[07:47] bunch of methods we're able to create chat completions which is like chatting to chatgpt and in order to create images using dial e we will call this create image method this method takes an object as its input and in this object we need to specify a few properties the first property will be the prompt as an example a puppy sniffing a flower the second property is in which represents the number of images that we'd like to generate or just set it to one for now and then the last property we want to
[08:19] specify is the size of the image the possible values is 256 by 256 512 by 512 or 10 24 by 1024 for this project it will simply set it to 512 by 512 the create image method is a promise which runs asynchronously and we need to await the response so I'll also add the await statement and we'll assign the response to a variable I'll just call that variable response after executing this function open II will return a URL to
[08:52] the image that was generated so we'll return that URL in the response of this API we can do that by replacing this hello in XJ is next with an object I'll add a property called data and this will be equal to our responseobject DOT data dot data we also need to stringify this response like so at the moment we are hard coding the string for the prompt but we'll replace this with a dynamic value a bit later on but for now we are done with this API we can now close the
[09:23] route file as well as the Tailwind config file so I only have the page file open and the global style sheets the the first thing I want to do is change some of the base styles for our application so the first thing I'll do is I'll specify the base layer and within base I'll specify the body tag and let's give our body a different background color you can do that by entering apply and then we'll start specifying telwyn CSS classes so I'll do a background color of gray 900 and the text of white let's go
[09:56] back to our application and we can now see that the background has changed and the text is white so back in page.js let's create a basic structure of our application we can go ahead and remove the sticks and I'll then add a few stalls to the main tag like container we'll also give it a Max width of 4XL and the margin left and right of Auto we then want to create a section for the prompt input field so I'll create a new tag called section which contains an H2 tag called prompt as well as an input
[10:28] field which is a self-closing tag and for input we can specify a few properties like the type of text a class name of full width and some placeholder text and this can really be anything you want but it's just to guide the user to show them how to enter a prompt so I'll enter a few examples here like a woman walking her dog a ballerina dancing a dog with glasses Etc you can also specify a default value to get the user started something like a dog playing
[10:59] with a ball we also need to add a few more styles to make this input look better so in the class name it's also add an outline of none padding top and bottom of two padding left and right of six a background gray of 600 or also around the corners with rounded XL and will make the text small cool let's also add a few styles to the section we'll align the content with flicks item center with a gap of two padding left and right of C and padding top and
[11:32] bottom of six below this plant our application will be split into two sections on the left hand side we'll have a button that says generate as well as the images that we generated on the right hand side we'll have a list of keywords that will assist the user with populating the prompt like in our application below this main section we will add another section I'll add some comments just to help us navigate this code we'll have a Dev that will contain the left hand side of the application and another Dev container for the right
[12:03] hand side of the application and in order to align these two items next to each other We'll add a few styles to this section over here we will align everything with grid with two columns and a gap in between the sections over Gap 4. let's start with the left hand side of this application the first thing we need is a button with the text generate let's give this button a few Styles so on the button I'll add class name We'll add a padding top and bottom of two padding left and right of six
[12:34] background lime of 600 or around the corners with rounded 3XL a text size of extra small and will convert the text to Upper guys we will also add a hover state for when the user hovers over the button and for this we'll change the opacity to 80 percent after saving this we can see the button as well as at hover State let's also add some stalls to this div so I'll add the class name keyword we'll align the items flicks Flex column with a gap of six padding
[13:04] left and right of six and a padding top and bottom of six as well then below the button I do want to show a placeholder block where the image will show up once it's generated for this I'll just create a div with a few classes we'll do a background gray of 600 an aspect ratio of square will align its context will align its content Flex with an items Center and the justify content of Center we can then add some content to this Dev
[13:34] and for this I'll just add the text image will show up here and after saving that this is looking good let's cover it with the right hand side of this app so in the right hand div We'll add an H2 tag with the text other options I do want to create some spicing between this header and the prompt section so let's give this div a clause of panning y 6. okay so let's write out our options now so first of all hard code this section
[14:05] and then we'll make it Dynamic so what we want to do is we want to create a new div with an H3 and we can give this a title like lighting we then want to list out all the keywords under this lighting section so in order to align these options correctly I'll create this wrapping div with a few Styles we'll actually just add a stall of grid flow row and then within this div We'll add each option as a button and I'll give this button a text like soft light as an
[14:36] example and let's actually add a few more examples so we've got soft light maybe something like Arc Light natural light Etc let's fix up the styling so on the H3 tag I'll add a few Styles We'll add a font of bold text small a margin bottom or four and a margin top of six then we'll add some styling on the individual buttons We'll add a padding top and bottom of two padding left and right of six a background gray of 600 all around
[15:08] the corners as well with rounded 3XL a text of extra small will force the text to uppercase and the margin of 2 all around we can go ahead and copy the styles to the other buttons right so we now have a section for lighting and when we click on these buttons we want the value of the button to be a painted to The Prompt so in order to do this we'll add an on click event on the button and when clicking the button we want to call a helper function called a paint prompt which will create and when clicking the
[15:40] button we will fire off a function and this function will call a helper function called a paint prompt let's create this function also when we call this function we want to posit a value and the value will be the word that we just clicked on and in this example the text will be soft lighting let's create this function so just above the return statement we can create our function called a paint prompt which takes in a word as input and what this function needs to do is it needs to paint this word to the current value of the prompt
[16:12] input field so to do this we need a reference to the input field itself in react we can add a reference to input Fields with I hook so at the top of the file we will import use ref from react after saving this you will get an error message this is because next 13 is server side by default if you need user interactivity in your application like what we need in this case we need to specify that this component is a client-side component so at the top of
[16:43] the file before this import we will simply say use client and that will resolve that error message we can now create a reference to the input field so within our home component I will specify any variable called prompt ref and I will set that equal to the use ref hook we now need to connect this variable to our input field so within our input field I will add a new property called ref and I'll simply pause in that variable name we are now able to access the value of this input field as well as
[17:15] change its contains So within the paint prompt function we will call promptrev Dot the current value dot current dot value which will create a link to the value of this input field we will set that equal to you the current value of the field Dot concat and we will concatenate the existing value of the field first with a comma then the word that was passed into this function this means that if I now click on the soft light button it should paint the value
[17:47] to The Prompt field let's try that out and that works great we now want to make this list of the different options and the buttons Dynamic so in the root of our project create a new folder called lib within lib create a new file called constants dot JS in constants it's export a new variable called options this will be an array of objects the first thing we want to set is the title of the option which in this example is
[18:18] lighting and then for this option we want to specify the available values which will also be an array I will pass in a few examples like soft lighting ambient Lights ring light neon light Etc you're welcome to add to this list as you see fit I will also add a few more options like environments color schemes and more and you're welcome to add to this list however you want you can find this full list in the GitHub repo Linked In the description now back in our
[18:48] project we will now replace all of this with some Dynamic code so what I recommend is if we cut all of this code and create a new component so I'll simply cut this then in the root of our project I'll create a new folder called components and within the component folder I'll create a new file called option dot JS we will now create a new react component which we can reuse to dynamically generate all the different options or create a new component called
[19:19] export default function option and this will return all of the stuff that we just cut from the main page file we will now dynamically render some of this content so I I will replace lighting with a dynamic title value we will get this title as a property coming into this component so in the parameter list or create a new object because we'll be destructuring these values from the properties and I'll call this title we will also expect to receive a list of
[19:50] available values so I'll remove these extra buttons so that we only have one button available for the button will dynamically render the text as well as well as the text that's passed through this function also there's a paint prompt function is not available in the component so this will also be passed to the component so in the properties I'll also add values as well as a function called on a paint so just above the button we'll Loop through the available
[20:21] values and dynamically render the buttons so we can expect values to be an array so I will enter values Dot app the individual items that be looping through or we'll just call Value and this function will return this button so I will just move the button up into this function we will also return this button component and we can now dynamically render out this content so for the button text I will set that equal to the value and instead of calling a paint
[20:52] prompt we will call on a paint and for the text we will also pass in value so just to recap what we'll do is we'll Loop through the list of options and for each option we will render out this option component we will pause in the title as well as the array of values into the component we will also pass in a function for a painting the text to The Prompt so what we'll do is we'll also pass in a paint prompt as the on a paint function enough talk let's just do
[21:24] it the first thing we need to do is import the list of options from this constants file so at top of our code under this import from react I will also call import options from add lib slash constants this ad symbol is called an alias and it's just shorthand for saying from the root of the project go to lib then Constance we also need to import our option component we can do that by calling import option from components
[21:55] slash option then in the right div underneath the heading we will map through the available options we will get each option as the input into this function which will return the option component as a self-closing component and we'll pause in a few props we need to pass in the title which we can get from option dot title we need to pause in the values prop which we can get from option dot values we also need to pass in the on a paint function which will
[22:27] reference the paint prompt function also in react when mapping through an array you need to specify a key prop which we will simply make equal to option dot title after saving this we can see all of our options pulling through as well as their values and clicking on these options will append them to the prompt back in our option component because we are mapping through the values we need to specify a key property on the root
[22:57] element as well so just before the on click event you will specify the key prop as equal to the value of the item excellent let's add the logic for generating the image right so what we'll do is back in the main page file on the generate button We'll add an on click event when clicking this button we'll call a Handler function called handle generate image and we'll go ahead and create this function I'll create it just below the supine prompt function so I'll
[23:28] call it handle generate image it doesn't take any parameters as inputs so what this function will do is it will take the value of our prompt and then pass it to our openai endpoint the endpoint should return a URL to the generated image which will then display in this block every year but first let's call that endpoint what I'll do is I'll wrap this call in a try catch block if we receive any errors I'll write them to the console then in our try block we
[24:00] will call the fetch API and we'll call the API slash open AI endpoint for the fetch API we also need to pause in a few more parameters so after the URL I'll specify this object the first property that we want to set is the method which in our case is a post method we'll also set the headers and for the headers we need to specify the content type as application slash Json after the editors we also need to specify the body and for the body we will pass in an object with
[24:32] a property of prompt and for this prompt property we will pass in the value of the prompt input field so we can reference the value of that field by calling prompt ref dot current dot value we also need a Json stringify this object so I will called Json Dot stringify and for wrap this object within stringify the fetch API returns a promise which we need to await and I will also assign this result to a variable called response in order to
[25:04] call a write we need to convert this function to an asynchronous function so before the parameter list I'll just add async and I can then save this after calling the fetch API we just have to check if the response was okay so we can say if response dot OK or at least if it was not okay we will throw a new error and we'll show some text like unable to generate the image if the response was okay we can then fetch the values from the response by calling a weight
[25:36] response dot Json let's actually console log this value for now like so let's go ahead and test this out I'm going to open up the console by going to the developer tools so we've got a prompt here called a dog playing with a ball let's click on generate and see what happens after a few seconds we got this object back and within data we can see that we've got one response at position zero which returned this URL back to us so it seems that the generation was
[26:06] successful so let's go ahead and show this image in our application we'll have to control this through state so from react I will also now import use State we will then create a new state variable for our image by specifying const and we will call this rendered image we will also specify a seter function called set rendered image and we will set that equal to use State and initially this will just be a blank array the reason I'm specifying an array instead of a
[26:38] single value is the fact that if we have a look at our route again we are able to ask our API to return more than one image back to us at the moment we will only return one image image but should you specify more than one we want the ability to Loop through the list of images and render them out on the screen what I also want to do is since it takes a little bit of time for the image to come back I want to create a loading State as well so below rendered image I will create another constant called loading with a Setter function of set
[27:10] loading we will set this equal to use State and initially the value will be false so back in this Handler function before we do any processing I want to set the loading state to true then once we're done with processing we want to set the state back to false so after the catch block I will add another block called finally the finally block will execute irrespective of whether our processing was successful or filed so in the finally block you will set loading
[27:41] to false in our try block if we got a successful response we want to set the rendered image to die data dot data which is an array then we can scroll down and add some code just below this div in fact we want to display this div this gray block over here only if we don't have any values in the rendered image state so we've all render this conditionally by adding these curly braces we will then say if rendered
[28:13] image dot length triple equals zero I'm going to change this name to plural images so I'll do that up here as well and I'll change the name of the seter function and I'll change it in the helper function as well so if rendered images is empty then we want to render this Square block so I'll move this div into this condition I'll add some logic just below this to say that if we have values in the rendered images then we
[28:45] want to map through those values this will give us each image and for each image we will return an image tag which is self-closing the source of the image will be the image dot URL because we're mapping through values we also need to specify the key which will also be image dot URL let's try this out let's click on generate we will wait a few seconds and as you can see we got a response
[29:15] back from openai and we are rendering the image to the screen what I want to do is while we are waiting for the response we want to disable this generate button and display different text so let's go back to this generate button I will add a property called disabled which is equal to the Loading state so while we are loading the loading state will be true which will mean that disabled will be true as well and we won't be able to click on the button it's also dynamically render the
[29:47] text I'll add these square brackets so we'll say if loading is true then we will write the text generating please wait else we will show the text generate let's try that out I will select a few of these options let's click on generate I see I've got a typo there so let's just fix the typo and let's try this again I'll click on generate I'm unable to click on the button while this is happening and once we get a result back we can see the image pulling through right we're nearly done with our
[30:18] application at the moment we click on generate we call our API and we are passing the value of prompt to the API as we can see here but if we go to our route file The Prompt is hard coded so in order to extract the prompt from the request we simply need to add the following line so we can call the Json function on the request and using the structuring we can grab the prompt we can then replace this hard coding with the prompt value Let's test this out we
[30:50] can leave the prompt as a dog playing with a ball and let's click on generate and there you go right and that concludes our tutorial you are now able to implement doll E2 in your own application if you would like to see how to deploy these projects to production you can have a look at my other videos on creating chatbots using openai and I will also be adding a video to my nextjs fundamentals course soon thank you very much for watching this video if you enjoy this content please consider subscribing it really helps support my
[31:21] channel I'll see you in the next one bye bye