Build a Support Agent with Vercel AI SDK – Full Tutorial

freeCodeCamp.org · Beginner ·🤖 AI Agents & Automation ·6mo ago

Key Takeaways

The video demonstrates how to build a customer support agent using the Vercel AI SDK, which streamlines text generation, embeddings, and structured outputs, and integrates retrieval augmented generation for more accurate answers. The agent makes autonomous decisions to answer questions or search the web in real-time, using tools like OpenAI API, Superbase, and PostgreSQL vector extension.

Full Transcript

The Verscell AI SDK is a TypeScript first toolkit for building AI features. It streamlines text generation, embeddings, and structured outputs. In this course, you will learn how to use the Verscell AI SDK to create and ship a customer support agent that makes autonomous decisions to either answer questions based on your support docs or search the web in real time. Mayo from Scribba developed this course. Welcome to the course on building a customer support AI agent with VCEL AI SDK and OpenAI. Now, over the past couple of years, we've seen how AI has transformed how we work. And one of the most exciting recent developments is the rise of AI agents. This allows the large language model to not be static but be able to trigger these different actions and make more autonomous decision-m thereby giving us more productive results. In this course, you're going to dive deep into the various strategies to help you build a production ready AI agent. We will be focusing on the use case of customer support to make this learning process easier for you. Now, we've seen the use case of AI as a chatbot where you ask a question and you get a quick response. But as I said, AI can go much further now with these agentic capabilities because of the ability to take action and call APIs and get into databases and do things like booking hotels online, interacting with websites, debugging code, performing deep research. And so now businesses are able to use these AI agents to automate complex tasks, synthesize information, and deliver long- form insights. Now, one of the most popular and powerful use cases is customer support. Why? Because customer support is at the heartbeat of every company. This is where complaints, bugs, and issues surface. and solving them well is essential to keeping customers loyal and happy. AI agents can make a huge difference here because they can first of all help to escalate and resolve issues quickly. Second of all, they automate responses to basic queries. So the human experts only focus their valuable time on the complex cases that the model cannot confidently resolve. Thirdly, they help to personalize support by retrieving details from past conversations or user profiles. Again, this is very useful for customer attention. And finally, they can help the company analyze customer interactions, uncover trends, problems, and even new product ideas. So in this course you will learn how to build exactly this type of AI agent that doesn't just generate text but intelligently routes queries retrieves real-time information and reduces hallucination. So firstly you will learn how to create logic so that the large language model will intelligently classify and route the user's query based on their intent. Secondly, you will learn how to build this AI agent that doesn't only just know when, but also how to retrieve relevant real-time information. You will learn the basics of using the popular VEL AI SDK, which will help you to simplify your workflow and speed up your development process. You'll also learn the integration of retrieval augmented generation for more accurate answers. And building this customer support AI agent in the end will enable you to see and have an application that is not just QA for documents but also the ability to perform web search and retrieve real-time information from the web. And so by the end of this course, you will have a working customer support AI agent that is a powerful real world application with actual real world use cases to dramatically improve the support experience for the users of whatever applications you're working on. Now this is what it's going to look like. Here we have asking a basic question. How do I join the Scrimmer Discord? And it's going to be trained on Scrimmer's help documentation. The results are shown below where the question is asked and the user is able to view the sources so they can see what documents or what specific pages were where the answer was retrieved from. And likewise, web search showing the other side of the autonomous decision the agent can make where the agent is able to go to the web to retrieve information because they identify that the answer was not available in the customer support docs. Now before we dive in, you should already know these. First of all, you should know how to use the OpenAI API, how to create an account, retrieve the API, and just work with APIs in general. Secondly, you should be comfortable with just crafting basic prompts. If you've done it on the chat chip interface, that is fine. Third, you should be comfortable with the concept of retrieval augmented generation. Now, we are going to go through a brief refresher in this course, but I highly recommend the scrimmer course if you are completely a beginner at what retrieval augmented generation is. Fourth, the implementation of basic function calls. You should be familiar with the idea of function calling. And fifth, creating basic express service for API routes. Again, Scriber provides a course that you can go through as a refresher. But don't worry if you're not super expert. I will walk you through the essentials as we go along in this course. Now, this is just a brief warning. This course is quite advanced. Okay? So the code is fairly complex and the challenges I've set are really going to make you think and work. So at the end of each scrim, make sure you take time to play with the code I have presented and really make sure you understand it before moving on to the subsequent challenge. With that being said, my name is May Ashen. I'm going to be in teacher in this course. I'm an AI engineering educator. I'm also the co-author of Learning Langchain published by O'Reilly. If you want to get my thoughts on technology, AI, entrepreneurship, you can follow me at Maya Ashin. With that being said, if you're ready to start building powerful AI agents that can make a real impact, let's get started. As discussed earlier, you should already have a basic idea of how retrieval augmented generation works and how it's used to create this question answer dynamic between a large language model and a user. Let's quickly recap. So what is rag? Rag is simply a mechanism where we store information somewhere. This could be a database or the web. And the user asks a question. We retrieve the most relevant pieces of information, pass it to the large language models context. the large language model is able to give the final answer that's contextually relevant. Now, why is this important? This is important because large language models are limited to data they're trained on. So, if you ask a question that's outside the training window, it may hallucinate or say it doesn't know. But with retrieval generation or rag, we can provide fresh contextual information so the model can give accurate answers it otherwise wouldn't know. So for example, if I ask the question, who are the most recent FIFA Club World Cup? The large language model may not know, but with retrieval generation, you can retrieve the fact that Chelsea Football Club beat Paris Sanjaman and then this is passed into context of the model so it can generate an accurate response. So where does this external data come from? Well, this is pulled from places like the web database, local text files. And in this course specifically, we'll be relying on a vector database. This is a special kind of database designed to work with embeddings. Now, embeddings are simply numerical representations of words, phrases, or even images. So if you plot them in this multi-dimensional space as you can see in the diagram semantically similar items will end up closer together. And when you ask a question what's actually happening under the hood is we convert the text into these embeddings and then we compare them against one another in the database and the closest ones are then retrieved as context and then passed so they can be used locally. Now, for the sake of this course, we are going to be using OpenAI's latest embedding model, text embedding three small. It's fast, it's accurate, and it's perfect for tasks like search recommendations, in our case, retrieving support documents relevant to answer the user's question. So, here's what to do. First of all, visit openai.com. Create an account if you haven't done so. Get the API keys and then go back to Scriber. Now, when you go back to Scriber, in the bottom right corner, click on the small gear icon and add a new entry called open AI API key. This is where you're going to paste the API key and save. So, at this point, you should understand what rag is, why it's important, have a basic grasp of embedding, and have your OpenAI key ready to go. So, with that being said, let's move on to the next lesson where we'll run our first function to generate embeddings and see what they look like in action. So, now we are in the code editor. I've already pre-installed the relevant libraries. At this point, you should have already saved your API keys in the edit environment at the bottom right. And so if you go to the config, we've essentially imported this OpenAI client from the OpenAI library. Everything's going to be pre-installed when you press run. So it would install everything in package.json, which is just essentially this OpenAI library. And then it will attempt to run start as well, which will trigger this file. So in the config, it checks if you've saved the environment variable, the API keys, and if you haven't, it's going to throw an error. We create the client and then we import into the main file. Now what we have here is OpenAI has a function called embeddings that allows you to create an embedding based on input text and all we're doing is passing this text will be converted to an embedding into input and then just console.log the results we get back. So if I click run open here we get the results. So this is the programmatic version of what embeddings look like. Essentially, embedding.data gives you an object that includes these different values. And it's important to see because you can see that all these unique numbers have been assigned to this block of text. And in the case of this particular embeddings model, there are 1536 dimensions. So here you can see three rows 6 7 8 9 and all the way down to you hit 1,536 different items in the array. And so this is essentially what the embeddings look like for this block of text. Now obviously if I change the text and when you change just press control S or command S to save the changes. Click run and you'll see a different group of numbers are generated because the text is different. And of course, if you eventually just want to access just the embeddings which we will later on to then pass on somewhere else, you essentially would need to first grab the first array here. So this is the only object inside. So again, the first item. Then you want to grab embedding dot embedding and then zero. So if I save control save should give value. There we go. So now we have the full array of embeddings and then we can pass this assign this to a variable and then pass it somewhere else. So you can play around here changing the different text just to have a feel for it. This is essentially the function that creates the embeddings. See you in the next lesson. Okay, so as discussed in previous lessons, a big part of retrieval meta generation is the ability to store data that you need somewhere else. Data that will be relevant to answering the user's question. And at runtime, we convert the question into embeddings. We retrieve by comparing the embeddings to the embeddings of stored data in a database. and then we pull the relevant documents back. In this course, we are going to use superbase to be the vector store or vector database that will store the embeddings of these documents that you eventually want to retrieve based on the user's question. So, Superbase is essentially a Postgress open-source database, but most importantly, it has a PG vector extension. This is just an extension that essentially allows us to work with embeddings at scale. Go to superbase.com. Once you're in superbase.com, follow the instructions to sign up and create an account. And then it's going to prompt you to create a new organization. Just create a free plan, personal, and just give your organization a name. Once you give your organization a name, you want to go in the middle of the web page, click on create new project, and then you'll be given an interface similar to this. Choose a region, East, US, or wherever is kind of closest to you. Give a database password you can remember and a project name. Maybe just call it Scrimmer customer support AI agent. Once you've created the project and you've created the organization, you're going to see an interface like this. And what you want to do is scroll all the way down to the bottom left. Click on the gear icon so you can go to the settings. When you're in the settings under project settings, move your mouse all the way down to API keys. Click on API keys. And then you're going to see this interface with what's known as your public key, which is safe to use in browser, and your service ro key, which essentially allows you to bypass raw level security and access any data in your database. For the sake of this course, we're just going to take both of them. So, make sure to copy both the public key and the service ro key. So, you click reveal and also copy that as well. Once you have both of these values, you want to come back, click on the gear icon in the bottom right of your scrim, and you're going to get the interface here. You've already saved your Open API key. So save your public key as the value for superbase URL and then superbase service key place the value of the service ro key here. So at this point you've set up Superbase URL and the Superbase service ro key. Now let's jump into the actual code. So now at this point you should have your OpenAI API key and your Superbase service ro key. And so this will allow you to create the Superbase client so you can access the database. As you can see, we've stored some dummy text and this text can be replaced with your own documents. But for the sake of demonstration, I'm just showing how we can take this, embed it, and then store it somewhere that we can retrieve later on. So, different topics, Magna Carta, Apollo, the history of computing, and so on and so forth. Here we have the logic for asserting the information from this text into the vex store. And here we have the main function. Now before we proceed, you need to go to created_tables.sql and copy this SQL command which will help you to enable PG vector extension and also create a documents table. You will pass in the content, any metadata and the embeddings associated with the content. Remember the model we're using is 1536 dimensions. So that is what we are going to pass in here. So command copy go back to your superbase interface UI. Now previously you were in the settings section. Click on this icon and this will open the SQL editor. When the editor is open it's going to have a button for you to create a new command essentially and just paste what you just copied in here and then click run. So once you've run inside the Superbase editor, it's going to create a table and it's going to create this extension. And so you will be able to see a table like this. Now it you will initially have an empty table until we finish this exercise here. But you should see a documents table here. Once you've completed this task before you've run the command, I'll just walk through what's going on here. Essentially, your source documents are in this directory. So we're going to fetch it. We're using text embedding three small as the model. Your table name is documents as per what we stored here. Here is an option. It's just a toggle I created that allows you each time you run this script to delete all the contents of your database. Uh it's just good for the sake of demonstration because then each time we rerun this or you rerun this, you don't have to think about merging content from a previous run. If you turn this to false, then every new run will just add new content to the documents table without removing previous content. So all we're doing here is going into the path, fetching the text, and what we're going to do is embed the file content. So you remember in the previous lessons, we discussed using the embeddings function to create embeddings based on content. So now we're just simply repeating that exercise except we just fetch the file content from the text file. We pass it here as input and then we store or we are creating objects that have content in the same object as the embeddings and metadata which include the source file name. And so this is very useful because when you later on retrieve the relevant documents, you're not just retrieving the content, you're also retrieving associated metadata which you can then use to basically see where the information came from. So once we're done creating the embeddings, all we're doing down here is using the superbase client from basically just points to the table and then insert command and we're just going to insert all the collected documents and that's it essentially. So if you go to index and you've done everything as per your API keys, all you need to do is click run. We should, as you can see, as per the terminal ingest with the source as text.txt. txt and you can see the embedding attached. We've uploaded one document to Superbase table documents. So then check your Superbase documents table. Make sure this text is there. You should see a table that consists of this text as a content metadata which should be source text.txt and then the embeddings. See you in the next lesson. All right. So based on the previous lessons, you should have already been able to create embeddings, understand what the role of the vex store is, and so we've taken the documents and we will visit splitting shortly in another lesson, but essentially we've taken the documents and we've embedded them and stored them in Superbase. So you should have already done that in the previous lesson and the document should be in your documents table in Superbase. Now in this lesson, we're going to go over this step, retrieval. The user asks a question, we convert the user's question into embeddings. We go into the veto store. The vector store is going to perform its similarity calculations to see which embeddings in the vector store are most similar to user's query. We retrieve the relevant portions and then we pass the prompt, the query the user provided plus the context of relevant docs in a final prompt that's sent to the model to generate an answer. So this is essentially what we're going to work on in this lesson. So jumping into the code, I will just walk through the changes we've made. We still have the documents folder in config. We still have superbase client and OpenAI. We've added a few things in the utils which I'll come to shortly. But one of them is the prompt that's going to be sent to the model which is going to pass in the user's question alongside the context. This context is what we are essentially trying to retrieve from the vector store based on the user's question. So essentially just to take the magic, this is what we're going to send to the model to generate an answer. And so our job is to essentially solve for this equation because we already know what the query is and we already know what the rest of the prompt is. We just need to fetch the context. And so we have this new logic called retrieve similar docs that will essentially help us to retrieve the relevant documents from the vex store. But before we do that, please go to created_tables.sql. And now I have new logic. Now in the previous lesson, you went to the superbase editor to create the documents table. This time just copy this whole thing. Go back to the editor and run it again. What is this doing? Essentially this is a database function that is going to help us to bind the relevant embeddings that are most similar to the user's query. So you have other variables here which we'll be able to pass in later on. We'll be able to say okay how many results should we return? What is the threshold? Right? So all embedding similarities are between 0 and one where one meaning that the two embeddings are very similar to each other and zero means that they're similar. So maybe you don't want to pass in too much polluted content into the models context. So you can adjust your match threshold. I've set 0.3 as default. And then here is just an optional filter that allows you to maybe filter based on metadata. And this is what you're going to get back from this match documents function. Coign similarity essentially is the calculation I discussed that is performed to essentially see which embeddings as close as possible to the user's query. Remember the user's query is going to be converted embedding. We're going to the vector store to also see which embeddings are similar to the user's query. So essentially this is a database function that once you've created it, we can then create this function here. So Superbase allows for the ability to make remote procedure calls to database functions. Remember you created this match documents database function. So we can make a remote procedure call here and then we can pass in the query embedding as we defined here the match count, match threshold and filter. In this case, I'm only going to pass the query embedding and the match count. And to get the query embedding, it's just what we've covered previously. You're just creating an embedding based on the query passed in as a parameter in here. So the query comes in, we generate the embedding response and then we pass in the embedding into the remote procedure call to trigger this database function that was created. And we've got in the constants fixed variable just a fetch five similarity count. Now we have also defined a new variable called the answer model. Why? Because in the previous lessons all we were doing was just retrieving the relevant documents. We didn't do anything with them. This time we're going to take an extra step. So if you come back here, if you just focus on retrieving the documents which is calling the retrieve similar docs based on this question which is covered in this document here, this text.txt. If I click run, what we're going to see in the terminal is we should see that we fetch the content and then this is what we expect. We expect an ID. We expect the content which will be the entire document because remember we embedded the entire text. We did not split the text into chunks. So there's only one block of text. And then we've got the metadata. And this is the cosign similarity I discussed previously. As you can see it's saying 50/50 in terms of how similar it is to the user's question. And that's because this text contains both the relevant information to answer the question which is right here in 1843 but it also contains a bunch of other irrelevant information that has nothing to do with the question. So that's why the similarity score is relatively low. So now we've retrieved the docs. The next step is to essentially create the prompt. And as I discussed previously, we are going to take these relevant docs, access the content property. That's what this function is doing. So we get the full string and then we pass in the context and the query to construct this final prompt that the model is going to use. Remember, every time you make changes, just control S or command S. Once we've created the prompt, we are now going to send the prompt to the model and then console.log the response from the model. So now we are going to press run just to generate the output. And so we're going to send the entire prompt to the model. Here we go. In 1843, Adah Love Lace published notes describing algorithms. She's often called the first computer program. So that is essentially coming from this block here. it's providing an answer based on what is saw in the text. And this is very different to just simply retrieving the relevant docs. You're now able to go into the vex store, retrieve relevant information, pass it as context in the final prompt, send the prompt to the model, and generate a final answer. So that is it in a nutshell. You can play around with this and when you're ready, I'll see you in the next lesson where we're going to discuss how to split this into chunks. So you can have more relevant chunks of text, embed those chunks and retrieve the relevant chunks as opposed to in this case we just retrieve one big block of text. But before we do that, let's have a challenge. So at this point, you should have embeddings of documents stored in your Superbase. And in this lesson, we'll be doing a short exercise where you're going to recreate building the retrieval mechanism we've discussed in previous lessons. You take a user's query as we have here. You embed that query using OpenAI's embeddings function down here. Then you retrieve the relevant docs from Superbase calling the RPC match documents function. And then you return the relevant docs. When you have the relevant retrieve documents, we already automatically create them into a single string. You create the prompt using the get rag prompt function from here. And then you pass in that prompt into OpenAI's model to generate a final response. And then you can see the relevant constants here including the model the simarity match cal and the embeddings model all here ready to be used in the functions provided. So in the end when you run this function you should be able to see the final generated answer based on the user's question. Now two things for housekeeping here. Number one, make sure when you're making changes, you press command S if you are on Mac or control S if you're on Windows to save your changes. And the second thing is make sure the question can be answers based on the context in the documents that you've stored in your Superbase. So for example, if in superbase you've stored content from the great fire of London from the previous text written lesson, then just keep this. If however you don't have that and you have something else or from the prior lesson, just make sure you change the query so that you can fetch relevant documents in the veto store. Okay, with that being said, go ahead with the exercise and I will come back to provide a solution shortly. Good luck. Hopefully you didn't find that too challenging. Let us start down here by first of all getting the embeddings response. Remember OpenAI provides embeddings function and all we're doing here is passing the embeddings model name and we've got the input which is the user's query. So done and dusted. We just need now to access the embeddings response. I believe that should be data zero and embedding. So now we should have the embedding corresponding to users query down here. You just want to get the documents and the match error from calling superbase. RPC and remember the database function is called match documents. And then we want to pass in the parameters. First of all, you are passing in the users embedding. So the the embedding of the query and then the match count how many relevant docs to return is limited to five which uh was passed previously. Okay. So now we have embeddings relevant docs and now we want to return the relevant documents similar to the users query. Now further up here we want to take the retrieve docs. This is the context. And now we want to pass in the query and the retrieve docs to construct the final prompt that will be used by the model and then finally construct the response. So the AI response is going to be taking in OpenAI responses create and then we're going to pass in the model on model which GT4 in this case and you can change that later on. The input is the prompt. Further down here we're just going to console.log response.output text and that should be it in a nutshell. So, AI response. And now, let's click run and see what we generate in the terminal. Voila. The Great Fire of London destroyed some 13,200 homes. That's exactly what we expect based on the relevant documents. We can see that that information is contained here in this chunk. Okay, fantastic. Well, great job so far. You've covered going over embeddings, recap on using the veto, retrieval, splitting using OpenAI. And now in the next lesson, we're going to move over into exploring Versile AI SDK, a library that will help to greatly simplify and abstract key logic for building AIC apps. See you soon. Okay, so in the previous lesson you have learned how to essentially construct a retrieval mechanism that will take a user's question, create some embeddings of the question, go into the vex store and compare the users's embeddings against what's in vex store, retrieve relevant documents, create the prompt and context and send to the model to generate an answer. Now we want to explore briefly an intermediate step as shown previously of text splitting. And essentially what is this? Now imagine we have this long document. This is just a passage from historical information on the great fire of London in 1666. Now, if you simply pass everything into the vex store and embed all of this as one chunk, what's going to happen is when you ask a question, as we've seen in previous situations, the vector store is literally just going to return this entire document. And this can be problematic for various reasons. First of all, maybe the user's question is only could be answered by a particular chunk of paragraph. And so by giving the model the entire context of the entire passage, you're essentially increasing the odds that it misses out on crucial details that may be required to answer the question. It could be as simple as this sentence right here, but the model might get confused or conflate with all the other information around that text. The second challenge with simply just grabbing the entire block of text is that your model might not be able to handle the full context window. As we know models are limited by context window of a number of tokens or characters they can pass in for any generation. Now obviously in this case this is relatively smaller passage or chunk of text but you could have for example a PDF of hundreds of pages of hundreds of thousands of character and you will not be able to pass everything into the same context window. So in order to overcome this issue, we need to find a way to essentially split our document into various chunks, embed each chunk and store each of them in separate rows in the table in Superbase. So the only adjustment or the main adjustment I've made here is to introduce this new function which is a very very basic simple text splitter. is going to take the text some sort of chunk size you provide how many characters to split the text into and overlap how many characters should overlap between each chunk. This is very very basic and only for demonstration purposes. As a matter of fact in this course for the most part we are not going to use text fitting but it is important for you to understand how it works and why it's important. So once we've done the text splitting or create this utility function, the obser documents logic has been updated. So if you scroll further down, you'll see that instead of just simply fetching the entire text and and embedding that, we first of all the document into chunks and we have stored the chunk size 2,000 characters in an overlap of 100, similarity of five and a threshold of 0.5. And so when we upsert this document, we are essentially going to chunk. Then after we create the chunks, we are then going to embed each chunk. So the only difference between this example and the previous time was previously we just took the entire document and we embedded it. And this time we are taking each chunk and we're embedding each chunk and we are adding a row for each chunk. So essentially you will end up with a table with multiple rows and each row is representing 200 characters of the block of text and the associated embeddings. So I'm going to run this function now. Go to your index.js and you can see the question how many houses were damaged and it's a very specific question inside corpus of text which can only be found in one sentence. So, we need precision. And so, this is a good use case for splitting. So, I'm going to click run in the top right. Let's see what we find. And you can see we've now embedded, we read 5,988 characters. We split into four chunks. And the different chunks were embedded into the vector store. Okay. So, now you have four rows. You can verify in your end instead of that one row with one block of text, you should have different rows now with each chunk. So I'm going to unc comment this and let's uncomment this whole block here. This is just a repeat of everything we learned in the retrieval lesson. We're going to go in the ve store pass in the users query. But you're going to notice something different this time. Actually before I generate this, let me just demonstrate what I mean. So now we're going to run again. And notice that we have fetched more than one block chunk of text. Right? In the previous lessons, you saw how it was just one block. But now you can see it's an array of multiple objects and each object represents a chunk of text that was embedded. And each chunk has a similarity score assigned to it saying how relevant it is to the question. And you can see that based on the query provided, we said how many houses were damaged during the great fire of London. And so you can see that this chunk already has the answer to the question because the answer to the question is 13,200 houses. And so this chunk has already succeeded in fetching the relevant portion. So imagine you had thousands and thousands and thousands and thousands of characters or words and what the embeddings approach has done is allowed you to just quickly retrieve this small chunk. So we can precisely provide this context to the model. You can see the similarity scores all above the match threshold that was set in the constants file. So you can see we have an array of different retrieve docks. Okay. Now we want to just complete the remaining steps as we did before. So just uncomment this and essentially we're taking creating the prompt with the chunks of text retrieved which is all of these text combined together as the context string. We then essentially pass in this prompt to the model and generate response. So let's click on run and see what happens. So now we're running and waiting for the response. And according to the context provided, approximately 13,200 houses were destroyed. And that's exactly what we expected based on the information here in this sentence right here or paragraph rather. So now you've seen how we've been able to basically take a a relatively large corpus of text, split into chunks, embed those chunks, and now we're able to have more precise answers to the question. So I hope this gives a good overview on dealing with inserting data into your database as embeddings, retrieving them, and answering questions. In the next lesson, we're going to explore the Versell AI SDK and discuss how this can streamline and make it much easier to build AIC apps. So, as discussed earlier in this course, we would later on interact with Versell AI SDK. Now, what is Versel AI SDK? It is essentially an open-source library by the Versell company, the same group and team behind Nex.js JS that essentially provides a unified interface to interact with LM providers. You can plug and play different providers. With the same interface, you can access very useful functions that are used for building AI apps and agents for generating text, generating embeddings, generating structured output, generating different steps that an agent can take, and it just simplifies the entire process. So it's a very useful library for us to use especially in this course. For example, you have a very simple generate text interface that you can import from the SDK. You provide your model and a prompt. That's it. If I want to swap OpenAI with cloud or any other model, it's very easy to do so as opposed to going through each of their documentations and finding their own different styles of generating an AI response. The same thing for embeddings. You can simply import embed from Versel AI SDK and use that unified interface. It doesn't matter what the model is, you can still get the same outcome. So now if we jump into the code, the config is still the same package.json, we've installed the AI SDK both here and here. And then finally, we have imported the OpenAI model that we're going to use as our AI model. So the key difference now between this and previous lessons is you are not using OpenAI's interface anymore. You're using the generic interfaces provided by the AI SDK. For example, here we want to generate text. We provided the OpenAI model and the prompt is write a brief p. So if I run this, we should see a brief poem that's been generated. The same applies to embedding. So let me comment this out and uncomment this. To generate embedding, you import the embed function from AI. You call the openi.ext embedding model and you just pass in the embedding model. The value is just whatever you want to embed. So this text will be converted to embeddings. I'll click run again and we see the text has been converted to embeddings. You will see we have a full 1536 items representing the embedding for the text. So all we've done essentially is taken the same concepts but instead of hard coding it to OpenAI's way of doing it, we have these generic interfaces. And this is going to be very useful for us moving forward as we begin to build AI agents that may potentially want to use one or more models depending on the strengths and capabilities each of them have. So that being said the basics I'll see you in the next lesson where we dive deeper into Brazil AI SDK. All right. In this lesson, we're just going to do a brief exercise to recap the basics of using Versell AI SDK. So the challenge is you are going to essentially replicate the logic before we're going to have a twist. So the goal is to generate text and embeddings using Versell AI SDK. You are going to implement the generate text interface in here. Uh pass it into a prompt to the model to create a recipe for your favorite meal. And then you're going to return the generated text from the model that is the recipe. Afterwards, you going to have that value assigned to text to embed. And text to embed is going to be passed into the generate embeddings function which is ready to take that text. Then we're going to embed that text using the embed interface. So that's the objective of this challenge. I'm going to give you a couple minutes to do this. go ahead and once you're done I will provide a solution. All right, hopefully didn't find that too challenging. So let's kick this off. So the first thing here if you remember from the previous lesson is we want to create an interface using the Versel AI SDK generate text. So we're going to have the text extracted from the weight generate text and inside here we are going to pass in the model which is the AI model already up here. So GT40 and then the prompt. So uh create a recipe for making pizza. So whatever your favorite dish is the idea here is to ensure that it's it's whatever your favorite. So say pepperoni pizza. Okay, so now we're going to send this off to the model. It's going to give us back the text and I'm going to console.log and say generated text which we'll pass in here and then finally return the text. Okay, so that way you can uncomment this and now text to embed should be the value of the text. So that's phase one and then phase two is use the embed interface to generate embedding. So we will already have the text to embed passed in as a parameter into this function. So all we have to do is extract the embedding from weight embed the model which is openi.ext embedding model and then you're going to pass in the embedding model. So this is the embedding model name value is going to be the text to embed. So this is what you want to embed which we've passed in which is the generated recipe of your favorite dish. And then here we're just going to console.log the embedding generated. Okay. So now we're going to run and see what happens. We can see generated texture. Here's a simple recipe for making delicious homemade pizza. Pizza dough. Teaspoons. Sugar. Olive oil. Salt. pizza toppings and so on and it's got instructions. We take all of this text and we generate the embeddings from the text and that's it in a nutshell. So now you've got the basics of how to use resell AI SDK to generate text and generate embeddings. In the previous lesson we discussed briefly the basics of Versell AI SDK to generate text and generate embeddings. But one of the more useful use cases especially in the cases of building aentic AI apps is the ability to generate structured output. So given the model instructions to give you back structured output. So then you can use that for something else. Maybe pass into another function that will call an API retrieve data or pass into another chain of the model so it can do something else. Now, one of the useful interfaces that Visel AI SDK provides to do this is the generate object interface. This is an interface that allows us to instruct the model to generate structured output in JSON format based on a predefined schema. When we mean schema, we just simply mean you're defining the data types, the properties you want, and the data types. Do you want a string, array, objects, and so on and so forth. And so for example down here we have a function called basic structured output using this generate object interface to essentially instruct the model to provide a structure JSON output of a recipe for pizza with the schema of object that contains name ingredients and the steps for creating the recipe and each property is defined by data type. a string. Ingredients is an array of objects with the name and amount and so on and so forth. And we're using this zed. Zed is imported from a library called zod. Zod is a popular library used to define schemas used to define a structure interfaces. So we're just simply accessing and using zod to help us to define the schema. So z.object simply means object. You're creating a schema. You're basically saying I want an object. Z.AR means you want an array and Z.RAY with Z.Object inside means an array of objects with name and property as strings. So when we tell the model generate a pizza recipe, we expect back a structured JSON object that contains name, ingredients, and steps. So let's run this and see what happens. Okay, so we're now running this. We've sent the instruction to the model. Please generate pizza recipe and give us back structured output. And here we go. The name which is a string which is what we expected. The ingredients which is an array of objects with name and object as strings exactly what we expected. And steps which is an array of strings. And that's literally how you can instruct the model to give you back a JSON in a structured output. You can see how this can be very useful to then instruct or pass on to another step in your program to invoke something else and create a chain of prompts or a chain of actions that's more agentic by nature. Another use case for structured outputs is classification. Now in this example, we gave a plain instruction and left the model to exercise some form of creativity. But classification is usually binary. So in this case, we want the model to classify the customer review using either positive or negative. So if you pay close attention, we're using a type enum. Enom is just a special data type that enables a variable to be predefined constants. So you can have more than one or two or even three or more enoms. But in this case, we want the model to give us a schema. Provide a JSON that contains the reason for why it's deciding positive or negative and whether the type is positive or negative. We also provide describe. Describe is just a useful property added to the ZOD schema to just help the model guide the model to know what you're looking for. So here I'm just further emphasizing that this is the sentiment of the customer review. And so again, we use the generate object interface and provide the model schema name, the description of your schema, the shape of your schema, what properties you expect back in the types of those properties, and finally the prompt. Let's run this and see what happens. Okay, so here we go. Reasoning the statement indicates satisfaction as the app performed as anticipated and type positive. And so we were able to classify the text provided by giving the model instructions using the generate object interface to give us a structured output and providing the enoms of what we expect. And so you can start to see how this can be very useful for classifying customer reviews, classifying customer requests, customer service. The structured outputs gives us the ability to provide more structure so that we can take and manipulate data types to do something down the line. So, in the next lesson, we're going to go over a brief exercise so that you can put this into action and begin to put this in memory as well. So, in the previous lesson, you learned how to create basic structured outputs using Versel AI SDK. In this lesson, we're going to do a brief exercise just to get you used to how the interface of generate object works and how Zod works. So, the first goal is to build a Zod schema. You're going to place a simple sandwich order. All the instructions are down here, including what each property should be and what the data type of each of them should should be as well and steps of being provided. Once you've completed that for this function, you want to uncomment here and run. After you've run, the next exercise is to build a Zod schema for classifying a short message. Again, all the instructions have been provided here. how to classify a short user's message based on what's being sent, what the message is. So this is the message that we are using and you will complete this as well. So I'm going to give you a couple minutes to work on this and once you're done I will provide a solution. Good luck. So hopefully that wasn't too difficult but we will go through everything slowly right now. So let's start off with the sandwich order. As you can see per the instructions, you can see the different data types as expected for the required fields to fill into Z.Object which you will then pass in as the sandwich schema. So let us begin. The first thing is the size. So we want size and we want an enum. Remember an enome is a constrained data type. So we can just pass in small, medium and large. And you can also provide a description just to help the model as well. Overall size of the sandwich. The next is bread. So as we said up here, bread is a string. So that's pretty straightforward. Z string and describe. This is the type of bread. Example, wheat, white, etc. The next data type is toasted. That's a boolean type. So toasted Z.Boolean describe and this is whether the sandwich will be toasted. We have toppings array of strings. So the data type has been provided to you here already. So you just pass in toppings Z array which is an array of strings and then minimum one at least one provided here. I think this is complaining because we didn't pass comma there. And describe one or more toppings like tomato, potato, lettuce, pickles, and finally the notes. So it's just an optional string. So you're going to do Zstring. Then you're going to pass in optional. So you're just letting know it's optional. and optional free text notes like cut in half. And so the prompt is here as we have provided previously for you. We have the sandwich order, a simple sandwich order, the schema has been provided and the console.log. So we're going to scroll up here, uncomment this and run and see what happens. Okay, so here's the structured output returned by the model. We can see the size is small. The bread is sourdough as we have the different choices here. Okay, so small sourdough bread toasted is a boolean says true. Toppings an array of strings exactly what we wanted and notes which is cut in half. So that is the basic structured output. Moving on to the next exercise about classifying the short user message. and to complete the message class schema that has been provided to you here. So let's start off with reasoning. So reasoning is a string and let's say describe and this is a brief explanation for why this label fits or however you wanted to describe that. So classify users message. We're providing a reasoning and then we're going to provide the label. The label is an also an enom. Let's put the comma here. So stop complaining. And this enom is going to take a compliment plaint. So we've got the reasoning and then we've got the label and let's also provide describe so that the model has a better description of what we want to achieve here. So highle category of the message. So this is the message schema and then you got the message here. You could also have a group of messages. So you could have a loop for basically an array of messages and then for each message you can loop over and generate the object for that particular message. So now we have the generate object. Now classify the user's message below. It's a promise sent to the model. And now we uncomment classification structured output exercise. comment the basic structured output exercise. And now we're going to go up and run and we should see the label is complaint. T

Original Description

Use the popular Vercel AI SDK to create and ship a customer support agent that makes autonomous decisions to either answer questions based on your support docs or search the web in real time. ✏️ Study this course interactively on Scrimba: https://scrimba.com/build-a-support-agent-with-vercel-ai-sdk-c0lk05ahir?utm_source=youtube&utm_medium=video&utm_campaign=fcc-vercel Vercel AI SDK is a TypeScript-first toolkit for building AI features. It streamlines text generation, embeddings, and structured outputs. It plays nicely with tools, so your agent can call functions like “search the web” or “query my knowledge base” safely and predictably. Scrimba on YouTube: https://www.youtube.com/c/Scrimba ⭐️ Contents ⭐️ 0:00:00 Customer Support AI Agent Intro 0:06:47 Retrieval Augmented Generation Refresher 0:10:05 Embeddings Recap 0:12:57 Vector Database Embed Documents 0:20:19 Vector Database Retrieval 0:28:00 Challenge: Vector Database Retrieval 0:32:51 Vector Database Text Splitting and Retrieval 0:40:34 Vercel AI SDK Basics 0:43:51 Challenge: Vercel AI SDK Basics 0:47:22 Vercel AI SDK Structured Outputs 0:52:38 Challenge: Vercel AI SDK Structured Outputs 0:58:39 Vercel AI SDK Tool Calling 1:08:37 Challenge: Vercel AI SDK Tool Calling 1:18:04 Agentic Retrieval Routing 1:31:52 Challenge: Agentic Retrieval Routing 1:35:08 Web Search AI Agent 🎉 Thanks to our Champion and Sponsor supporters: 👾 Drake Milly 👾 Ulises Moralez 👾 Goddard Tan 👾 David MG 👾 Matthew Springman 👾 Claudio 👾 Oscar R. 👾 jedi-or-sith 👾 Nattira Maneerat 👾 Justin Hual -- Learn to code for free and get a developer job: https://www.freecodecamp.org Read hundreds of articles on programming: https://freecodecamp.org/news
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from freeCodeCamp.org · freeCodeCamp.org · 0 of 60

← Previous Next →
1 React: Production Server Setup Part 2 - Live Coding with Jesse
React: Production Server Setup Part 2 - Live Coding with Jesse
freeCodeCamp.org
2 cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
freeCodeCamp.org
3 Browser history tutorial - Beau teaches JavaScript
Browser history tutorial - Beau teaches JavaScript
freeCodeCamp.org
4 Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
freeCodeCamp.org
5 React: Parameterized Routing with Next.js - Live Coding with Jesse
React: Parameterized Routing with Next.js - Live Coding with Jesse
freeCodeCamp.org
6 React: Dealing with jQuery Issues - Live Coding with Jesse
React: Dealing with jQuery Issues - Live Coding with Jesse
freeCodeCamp.org
7 setInterval and setTimeout: timing events - Beau teaches JavaScript
setInterval and setTimeout: timing events - Beau teaches JavaScript
freeCodeCamp.org
8 Browser and Device Testing - Live Coding with Jesse
Browser and Device Testing - Live Coding with Jesse
freeCodeCamp.org
9 Last Minute Updates - Live Coding with Jesse
Last Minute Updates - Live Coding with Jesse
freeCodeCamp.org
10 Post Launch Updates - Live Coding with Jesse
Post Launch Updates - Live Coding with Jesse
freeCodeCamp.org
11 React: Setting Up Google Analytics - Live Coding with Jesse
React: Setting Up Google Analytics - Live Coding with Jesse
freeCodeCamp.org
12 React: Masonry Layout - Live Coding with Jesse
React: Masonry Layout - Live Coding with Jesse
freeCodeCamp.org
13 Load Balancing Digital Ocean Droplets - Live Coding with Jesse
Load Balancing Digital Ocean Droplets - Live Coding with Jesse
freeCodeCamp.org
14 try, catch, finally, throw - error handling in JavaScript
try, catch, finally, throw - error handling in JavaScript
freeCodeCamp.org
15 Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
freeCodeCamp.org
16 Graphs: breadth-first search - Beau teaches JavaScript
Graphs: breadth-first search - Beau teaches JavaScript
freeCodeCamp.org
17 React: Masonry Layout Part 2 - Live Coding with Jesse
React: Masonry Layout Part 2 - Live Coding with Jesse
freeCodeCamp.org
18 React: WordPress API Live Search - Live Coding with Jesse
React: WordPress API Live Search - Live Coding with Jesse
freeCodeCamp.org
19 Creating WordPress Custom Post Types - Live Coding With Jesse
Creating WordPress Custom Post Types - Live Coding With Jesse
freeCodeCamp.org
20 Dates - Beau teaches JavaScript
Dates - Beau teaches JavaScript
freeCodeCamp.org
21 Miscellaneous Front End Updates - Live Coding with Jesse
Miscellaneous Front End Updates - Live Coding with Jesse
freeCodeCamp.org
22 Merging a Pull Request from GitHub - Live Coding with Jesse
Merging a Pull Request from GitHub - Live Coding with Jesse
freeCodeCamp.org
23 React + Prettier + Standard JS - Live Coding with Jesse
React + Prettier + Standard JS - Live Coding with Jesse
freeCodeCamp.org
24 React: Sortable Responsive Table - Live Coding with Jesse
React: Sortable Responsive Table - Live Coding with Jesse
freeCodeCamp.org
25 Geolocation Sorting by Distance - Live Coding with Jesse
Geolocation Sorting by Distance - Live Coding with Jesse
freeCodeCamp.org
26 Tradeoff Matrix - Agile Software Development
Tradeoff Matrix - Agile Software Development
freeCodeCamp.org
27 The Definition of Ready - Agile Software Development
The Definition of Ready - Agile Software Development
freeCodeCamp.org
28 Getting first React job without experience - Ask Preethi
Getting first React job without experience - Ask Preethi
freeCodeCamp.org
29 React: Google Analytics Click Tracking - Live Coding with Jesse
React: Google Analytics Click Tracking - Live Coding with Jesse
freeCodeCamp.org
30 Submitting a PR to an Open Source Project - Live Coding with Jesse
Submitting a PR to an Open Source Project - Live Coding with Jesse
freeCodeCamp.org
31 Should I go back to school to get CS degree? - Ask Preethi
Should I go back to school to get CS degree? - Ask Preethi
freeCodeCamp.org
32 Hero Section CSS Changes - Live Coding with Jesse
Hero Section CSS Changes - Live Coding with Jesse
freeCodeCamp.org
33 Working Agreement - Agile Software Development
Working Agreement - Agile Software Development
freeCodeCamp.org
34 A day at Pennybox with Co-Founder Reji Eapen
A day at Pennybox with Co-Founder Reji Eapen
freeCodeCamp.org
35 React: Sorting and Filtering Data - Live Coding with Jesse
React: Sorting and Filtering Data - Live Coding with Jesse
freeCodeCamp.org
36 React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
freeCodeCamp.org
37 React: Building a New UI - Live Coding with Jesse
React: Building a New UI - Live Coding with Jesse
freeCodeCamp.org
38 Definition of Done - Agile Software Development
Definition of Done - Agile Software Development
freeCodeCamp.org
39 Getting started with jQuery (tutorial) - Beau teaches JavaScript
Getting started with jQuery (tutorial) - Beau teaches JavaScript
freeCodeCamp.org
40 Making a React Blog with WordPress Content - Live Coding with Jesse
Making a React Blog with WordPress Content - Live Coding with Jesse
freeCodeCamp.org
41 React, NextJS, CSS - Live Coding with Jesse
React, NextJS, CSS - Live Coding with Jesse
freeCodeCamp.org
42 jQuery events - Beau teaches JavaScript
jQuery events - Beau teaches JavaScript
freeCodeCamp.org
43 React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
freeCodeCamp.org
44 React: Working with API Data - Live Coding with Jesse
React: Working with API Data - Live Coding with Jesse
freeCodeCamp.org
45 React: Refactoring Components - Live Streaming with Jesse
React: Refactoring Components - Live Streaming with Jesse
freeCodeCamp.org
46 jQuery effects - Beau teaches JavaScript
jQuery effects - Beau teaches JavaScript
freeCodeCamp.org
47 More React Refactoring - Live Coding with Jesse
More React Refactoring - Live Coding with Jesse
freeCodeCamp.org
48 animate in jQuery - Beau teaches JavaScript
animate in jQuery - Beau teaches JavaScript
freeCodeCamp.org
49 "Finishing" My React Site - Live Coding with Jesse
"Finishing" My React Site - Live Coding with Jesse
freeCodeCamp.org
50 Starting a New React Project (P2D1) - Live Coding with Jesse
Starting a New React Project (P2D1) - Live Coding with Jesse
freeCodeCamp.org
51 React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
freeCodeCamp.org
52 The Agile Manifesto - Agile Software Development
The Agile Manifesto - Agile Software Development
freeCodeCamp.org
53 jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
freeCodeCamp.org
54 React Project 2 Day 3 - Live Coding with Jesse
React Project 2 Day 3 - Live Coding with Jesse
freeCodeCamp.org
55 The INVEST approach to product backlog items
The INVEST approach to product backlog items
freeCodeCamp.org
56 React Project 2 Day 4 - Live Coding with Jesse
React Project 2 Day 4 - Live Coding with Jesse
freeCodeCamp.org
57 Chickens and Pigs - Agile Software Development
Chickens and Pigs - Agile Software Development
freeCodeCamp.org
58 React Project 2 Day 5 - Live Coding with Jesse
React Project 2 Day 5 - Live Coding with Jesse
freeCodeCamp.org
59 jQuery: add and remove DOM elements - Beau teaches JavaScript
jQuery: add and remove DOM elements - Beau teaches JavaScript
freeCodeCamp.org
60 React Project 2 Day 6 - Live Coding with Jesse
React Project 2 Day 6 - Live Coding with Jesse
freeCodeCamp.org

This video teaches you how to build a customer support agent using the Vercel AI SDK, which integrates retrieval augmented generation for more accurate answers. You'll learn how to use tools like OpenAI API, Superbase, and PostgreSQL vector extension to create a support agent that makes autonomous decisions to answer questions or search the web in real-time.

Key Takeaways
  1. Create an account on openai.com and get the API keys
  2. Add the API key to Scriber
  3. Install the OpenAI library using package.json
  4. Run the program to generate embeddings
  5. Create a Superbase account and organization
  6. Create a new project in Superbase and set up API keys
  7. Copy OpenAI API key and Superbase service ro key
  8. Create a Superbase client to access the database
  9. Store dummy text in the database and replace with user documents
💡 The Vercel AI SDK provides a unified interface for building AI features, including text generation, embeddings, and structured outputs, making it easier to create a customer support agent with retrieval augmented generation capabilities.

Related Reads

Chapters (16)

Customer Support AI Agent Intro
6:47 Retrieval Augmented Generation Refresher
10:05 Embeddings Recap
12:57 Vector Database Embed Documents
20:19 Vector Database Retrieval
28:00 Challenge: Vector Database Retrieval
32:51 Vector Database Text Splitting and Retrieval
40:34 Vercel AI SDK Basics
43:51 Challenge: Vercel AI SDK Basics
47:22 Vercel AI SDK Structured Outputs
52:38 Challenge: Vercel AI SDK Structured Outputs
58:39 Vercel AI SDK Tool Calling
1:08:37 Challenge: Vercel AI SDK Tool Calling
1:18:04 Agentic Retrieval Routing
1:31:52 Challenge: Agentic Retrieval Routing
1:35:08 Web Search AI Agent
Up next
How to Setup OpenClaw for FREE on Raspberry Pi 5 | Full Ollama & AI Agent Guide
Ksk Royal
Watch →