
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
Complete source code for this lesson is available at
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:02 Let's create an API route that'll generate an AI response to a question using the Vercell AI SDK.
00:00:08 First things first, we have to install that SDK.
00:00:11 So open up your terminal and run npm install ai as well as ai-sdk forward slash openai.
00:00:22 And don't miss this at sign at the start of ai-sdk.
00:00:26 press Enter, and wait until it gets installed.
00:00:30 Now, similar to what we used to do with server actions, we also need the validation schema to validate the body data passed to the API we'll create.
00:00:39 So let's head over into validations.ds, and let's create a schema for the AI answer.
00:00:46 We can do that by saying export const ai answer schema, and we can make it equal to z.object that starts with a question.
00:00:59 So within the answer, we still wanna keep some information about the question.
00:01:02 So I'll say question is z.string with a min of five characters.
00:01:09 And the message can be something like question is required.
00:01:12 And we can also give it a max of about 130 characters and say something along the lines of message, questions cannot exceed 130 characters.
00:01:22 After the question, we'll also render the content.
00:01:25 This is the main part of our answer.
00:01:28 So the content will be z.string.min of 100 characters.
00:01:33 And we can also render a message of saying something like answer has to be more than 100 characters.
00:01:39 And now we are ready to create our API route.
00:01:43 We can do that by heading over to our app, API, And we can create a new folder called AI.
00:01:51 And within AI, we can create another folder called Answers.
00:01:56 And within Answers, we can create a new API route called route.ts.
00:02:02 Within it, we can import OpenAI.
00:02:05 coming from at ai sdk openai.
00:02:10 We can also import generate text, which is coming from ai.
00:02:14 And these are the two most important functions we'll use to implement our ai logic.
00:02:20 But now we still need a regular post route.
00:02:23 So let's export async function post, which will accept a request of a type request.
00:02:32 And we can open up a function block.
00:02:35 Within it, we can destructure some data from the JSON by destructuring the question as well as the content.
00:02:43 And that is coming from, or rather is equal to await rec.json.
00:02:49 Then we can open up a new try and catch block.
00:02:53 In the error, we can just return handle error coming from libhandler's error.
00:02:58 We can pass in the error as well as the API note.
00:03:03 This is the type of the response we're working with as API error response.
00:03:09 And in the try, we can validate the data we're passing into this API call by saying const.
00:03:16 validatedData is equal to ai answerSchema, coming from libvalidations.safeParse.
00:03:27 And to it, we can pass an object containing the question as well as the content.
00:03:33 Finally, if there is no validated data, we'll return the handle error and then pass in the validated data dot error.
00:03:42 But we can also flatten the error to know exactly what error we have with it.
00:03:46 So validated data dot error dot flatten and then dot field errors.
00:03:52 So we know exactly what is missing.
00:03:55 And no need to provide information on what kind of error this is.
00:03:59 So it'll look something like this.
00:04:01 Oh, but actually what we can do is not call the handle error.
00:04:04 We can rather throw a new validation error.
00:04:10 We have already created that one coming from lib-htps-errors.
00:04:14 And then we can wrap the actual error within it.
00:04:17 That way we know what we're dealing with.
00:04:20 We can remove this return because we're throwing it and we're good.
00:04:25 Finally, let's generate some text.
00:04:27 Let me show you just how easy it is.
00:04:30 I'll say const, destructure the text, and make it equal to an await call to the generateText function.
00:04:39 Yep, it is that simple.
00:04:42 Vercell made it so simple to generate AI text.
00:04:45 And the function name just makes sense.
00:04:47 GenerateText coming from AI.
00:04:50 Now to it, you can provide an object with some additional information, such as the model, like which model you want to use.
00:04:58 In this case, I'll use the OpenAI model.
00:05:01 And within a string, I can provide which specific model I want to use.
00:05:05 In this case, I'll say GPT-4-Turbo.
00:05:11 If you have another model you prefer, you can use that one.
00:05:15 Then we can define a prompt that we want to pass to it and I'll do something like this.
00:05:22 Generate a markdown formatted response to the following question and then I'll provide the actual question Right here.
00:05:36 Of course, we're passing this through request params into this function call or API call, should I say.
00:05:42 And I'll also say based on the provided and pass the content.
00:05:49 That'll look something like this.
00:05:50 Create a marked and formatted response to the following question.
00:05:54 We pass the question.
00:05:55 I'll put a dot here and then say, base it on the provided content.
00:06:00 And then we pass the content.
00:06:01 Of course, the content here being the answer that the user has already typed.
00:06:06 So it'll take that into consideration, but it'll just improve it and turn it into a marked and formatted proper response to that question.
00:06:14 And another prop you can pass into this generateText function is something called the system.
00:06:20 Here, you can tell it a bit more information about what exactly this AI is and how it should respond.
00:06:27 I was playing around with the prompt a bit and ultimately came up with this.
00:06:32 You are a helpful assistant that provides informative responses in Markdown format.
00:06:38 Use appropriate Markdown syntax for headings, lists, code blocks, and emphasis where necessary.
00:06:44 For code blocks, use short form for smaller case language identifiers like JS for JavaScript, PY for Python, or TS for Tabscript,
00:06:53 HTML for HTML, CSS for CSS, et cetera.
00:06:56 We're just giving it some info so it knows how to properly format the answer.
00:07:00 I'll leave this text below the lesson so you can copy it and add it here as well.
00:07:05 Finally, once we get the text, we are ready to return it.
00:07:08 By saying return, next response coming from next server, dot json and we're going to simply return a success of true and the data of text.
00:07:21 Outside of it we can also pass a status of 200. Perfect.
00:07:27 And now we should be able to test out this API endpoint.
00:07:31 You can use any kind of HTTP client to do it.
00:07:34 There are many clients like Thunder Client built right into your code editor.
00:07:38 There's also tools like Postman or Insomnia.
00:07:42 And as of recently, I started using this one called HTTPy, which is super simple to use.
00:07:47 So let me show you how.
00:07:49 I'll just make a post request to localhost 3000, forward slash API, forward slash AI, forward slash answers, and I'll pass in the request body.
00:07:59 I'll pass it as plain text.
00:08:01 Here, you'll have to pass some kind of a JSON object with a question and an answer, or in this case, it'll be content that it'll base the answer off of.
00:08:13 So now if you try making that post request and click send, you'll see that we have a 500 internal server error.
00:08:20 Then if you check the terminal, you'll see that our server indeed did send a 500 and it did that because it couldn't find open telemetry API.
00:08:30 Interesting.
00:08:31 This should already be a part of the packages that we installed, but sometimes packages get messed up.
00:08:37 It used to happen to me before too.
00:08:39 So what you can do is make sure that you install the packages that I have right here, like AI SDK OpenAI and AI, and then delete your package log JSON,
00:08:50 as well as delete the node modules And then when you do that, just run npm install one more time.
00:09:00 This way we'll have a clean slate on all of our packages.
00:09:03 And then you can rerun your application by running npm run dev.
00:09:07 And then if you resend it, you should get a different kind of error, this time a 400, which is exactly what I want it to get.
00:09:14 Because this one says that we're not passing the proper info into this request.
00:09:19 question is required, and answer has to be more than 100 characters.
00:09:22 So, if you pass it correctly, with a question like, what is the difference between SQL and NoSQL databases, and with the answer where you tried explaining
00:09:31 some of that stuff already, but now you want AI to modify it for you, to enhance it, let's put it that way, because AI is never ideal for writing stuff,
00:09:40 but it's better for improving all the existing stuff.
00:09:44 So, if you now click Send, you'll get back a 200, hopefully.
00:09:49 Keep in mind that AIs do take some time to generate that response, so currently the transaction is still in progress.
00:09:57 But there we go, we got back a success true with a data that is now structured with a Markdown format.
00:10:04 We have a double hash indicating a heading two, some new line characters, and more.
00:10:10 Beautiful.
00:10:11 This means that everything is working well and that we're getting back the responses.
00:10:15 So back within our code, head over to our API.ts file where we are configuring our API for auth, users, and accounts.
00:10:25 Now we'll add an additional one called ai where I'll create a new function called getAnswer and this one will accept a question as a string as well as
00:10:40 content as a string but we already know that and it'll return an API response of a type string.
00:10:50 So let's immediately open up a function.
00:10:53 Don't open up a function block.
00:10:55 Just put the arrow function here, and then automatically call the fetch handler to which you can pass the base route.
00:11:05 So that'll look something like this.
00:11:07 API base URL, forward slash AI, forward slash answers.
00:11:13 Make sure that this AI route is exactly as we declared it right here.
00:11:17 App, API, AI, answers, plural, and then route.
00:11:22 So it has to be answers.
00:11:24 And then you can pass some additional options, such as maybe a method of a type post.
00:11:32 As well as, and most importantly, the body, which will be a JSON.stringify of an object that has access to the question and the content.
00:11:43 Beautiful.
00:11:44 Let's go ahead and commit this by saying AI answer, API route, commit and sync.
00:11:51 And in the next lesson, we are ready to use this newly created API route to generate an answer for real.