Learn LangChain.js - Build LLM apps with JavaScript and OpenAI

freeCodeCamp.org · Beginner ·🔍 RAG & Vector Search ·2y ago

Key Takeaways

This video teaches how to use LangChain.js to build LLM apps with JavaScript and OpenAI, focusing on retrieval-augmented generation and conversational retrieval over documents. It covers setting up a vector store, creating embeddings, and building a chatbot that can answer questions based on a knowledge document.

Full Transcript

this course will help you master Lang chain a revolutionary AI first framework Lang chain enables developers to build context aware reasoning applications by linking large language models with external data sources for advanced natural language processing applications starting with the basics of text processing and vectorization and advancing to the nuanced aspects of laying chains expression language and retrieval techniques you'll gain hands-on experience in building real world AI applications Tom chant developed this course he is an experienced developer and course creator at scrimba hey there free code campers and welcome to this interactive course where you're going to learn how to use Lang chain JS to build a context aware chatbot that can answer questions on a specific document we provid it we're starting with the basics so you don't need any prior experience with Lang chain JS or even with AI the only prerequisites for this course are a knowledge of working with apis and vanilla JavaScript now Lang chain has a reputation for a steep learning curve but using its new expression language we make the journey much easier this is a Project based course with challenges and that means you're going to get your hands on the keyboard writing code throughout and if you're wondering how you can access the project code don't worry we've got you covered from the interact active version of this course on sca.com you can pause the video edit the code and run the projects right there in your browser or you can download the code from the scrims and run them locally if you prefer the link is in the description and one final thing if you enjoyed this course do hit the thumbs up right here on YouTube and if you'd like to get in touch reach out to me I'm on Twitter or X at TP chant okay let's Dive In hang chain to build aiiowed applications I am super excited to bring you this course on using one of the most mind-blowing Technologies in the emerging AI Universe we are going to study embeddings we'll be working with Vector stores we'll be building templates and creating prompts from those templates next we'll look at setting up chains and we'll do that using Lang chains expression language which is a more expressive and accessible way to write Lang chain we'll be looking at the pipe method to join elements of a chain together we'll be retrieving data from a vector store and then we'll use the runnable sequence class which is a really cool way to create complex chains in Lang chain and there's loads more plus challenges this is our project we are building a bot which is knowledgeable on information we give it so this bot is going to know all about our platform sca.com and we're going to feed it 3,000 words of information and then we'll be able to interrogate it on this information this is one of the most powerful uses of AI and it's a process that Lang chain makes easy now in this course we're going to focus on the Lang chain syntax the project is built in vanilla JavaScript and you're welcome to refactor it into any framework or Library you wish I'm assuming you have a solid knowledge of vanilla JavaScript but you don't need to be an expert if you've worked with apis and asynchronous JavaScript a little bit before you're going to be absolutely fine my name is Tom chant and I will be your tutor for this course you can find me on Twitter or X or whatever you want to call it I am @ TP chant and you can click this link and visit me there it's always good to hear how you got on and any feedback you might have now before you begin why not head over to our Discord server and meet the community and let everybody know that you're starting this course in the today I will Channel and again this slide is a link to that page on our Discord server before we we dive into the concepts and code let's get an intro to Lang chain from the founding software engineer of Lang chain Jacob Lee Yes L chain is a framework that helps developers build context aware reasoning applications Lang chain was born out of the realization that the process of developing sophisticated AI powered apps could be significantly streamlined by factoring out some common abstractions while much of current AI app development akes place in the realm of python there's a clear need for better tooling for the more webd focused JavaScript Community too hence L chain comes in two flavors and one of the aims of Lang chain JS is to make large language models and techniques around working with them more accessible to this broader audience in this course you'll be learning how to use Lang chjs to build your own apps it focuses in on conversational retrieval over document giving an llm access to the specific information in that document so it can answer questions and continue a logical contextualized conversation on topics Beyond its original training data along the way you will use models prompts and Alpha parsers some of the basic building blocks of lank chain we'll create chains of calls that enable us to connect up the various stages in the process need to get the desired output we'll be using L chain with superbase and the open AI API but one of the beauties of this framework is that components are easily swappable so you can work with a myriad of databases Vector stores and llms switch between them and find the one which works for you best good luck and I really hope you enjoy this course and enjoy using L chain to spin up really powerful AI web apps of how this app is going to work in this first section we need to work with our data so this chatbot is going to be knowledgeable about a specific Topic in this case the scrimber platform so we're going to start off with an information source which holds the knowledge we want the chatbot to have and we're going to pass this document to a splitter and the splitter is a lang chain tool which will split the document into chunks and then we're going to use an embeddings model from open AI to create vectors from each chunk and we're going to save those chunks to our Vector store which in this case is going to be a superbase vector store when we get to this point the vector store is established it's got all of the knowledge we want it to have and we won't need to repeat this process unless we want to give it more knowledge by adding some new data now if you don't understand the justification for each step or you're not really clear on vectors and embeddings yet don't worry we're going to go into a lot more detail when we actually write the code this is just an overview now once we've got the vector store set up we need to create the app to use it and the flow of that app is going to look like this we start off with a user which we've got represented right here and that user will input something probably a question they have about scrimber and we're going to do two things with that question we're going to save it to a conversation memory store which will hold the entire conversation and we'll use an open AI model to convert it to a standalone question and that just means we're going to reduce it to a very concise question with no unnecessary words we'll then take that Standalone question and we'll use an open AI embeddings model to create vectors from it we'll send those vectors to our superbase Vector store and we'll get back the chunk or chunk with the nearest match therefore the chunks that are most likely to contain the answer to our question the last stage is to use an open AI model to get the final answer and to give it the best chance of getting a good answer we're going to give it three pieces of information we're going to bring down the nearest matches from the vector store we'll give it the original user input and we'll also give it the conversation memory which will be the entire conversation that has taken place so far so that might be a very very long conversation or this might be the first question in the conversation now we're going to take the response that we get and we'll store it in the conversation memory ready to continue the conversation and also we'll give it back to the user by rendering it to the Dom now again this is a very high level overview and it might well cause some confusion for example what actually is a standalone question and why are we using it right here but then down here we're using the original user input and not the Standalone question but rather than get caught up that right now and give very theoretical answers what I want to do is keep referring to this diagram as we write the code and we're going to tackle those questions as they come up one by one so if this diagram looks horribly confusing right now don't worry at all we are going to take it step by step okay in the next Grim let's go right back to the beginning and think about getting some data into our Vector store but before we do that I'm going to bring in a scrim from my colleague Gil who's going to give you a detailed overview of embedded ings so sit back and take a few minutes to watch that next powered search shapes many parts of your daily lives every day you interact with platforms sifting through massive amounts of data from text and images to audio and video think about Amazon recommending products or search engines refining your queries social media platforms curate tailored content while services like YouTube Netflix and Spotify offer suggestions based on your preferences now Advanced AIS despite their capabilities don't truly understand the real world as we do they can't grasp the actual meaning or Nuance of a video title song or news article so how exactly do AIS and platforms like Spotify Netflix and YouTube truly get us how is it that they appear to understand predict and respond to us as effectively as if not better than people well the magic behind this capability involves a blend of algorithms AI models and huge amounts of data but a larger part of the answer involves embeddings you see when you present a question to an AI it first needs to translate it into a format it can understand so you can think of embeddings as the language that AI understands the term embedding is a mathematical concept that refers to placing one object into a different space think of it like taking a word or sentence which is in a Content space and transforming it into a different representation like a set of numbers in a vector space all while preserving its original meaning and the relationships between other words and phrases AI systems process lots of data from user inputs to information and databases at the heart of this processing are embeddings which are vectors representing that data transforming content like search queries photos songs or videos into vectors gives machines the power to effectively compare categorize and understand the content in a way that Almost Human so how is all of this possible well it isn't exactly as easy as just turning data into vectors so before we go any deeper let's take a closer look at what vectors are think of a vector as a coordinate or point in space and to keep things simple we'll have a look at this 2D graph with an X and Y AIS let's say that a word like cat is translated into a vector like 4.5 12.2 which is this point this Vector encapsulates the meaning and nuances of the word cat in a way an AI model can understand and then we have the word feline represented by a nearby Vector of 4.7 12.6 so we'll place that point on the graph now words that have similar meanings are numerically similar and tend to be closely positioned in the vector space so this closeness implies that cat and Feline have similar meanings now let's say we have the word or vectors for kitten which might also be close to cat and Feline but maybe slightly further apart due to its age related Nuance now a dog dog is different but still in the same general domain of domesticated animals so the word dog might be represented by a vector that's not too distant but clearly in a different region let's say 7.5 10.5 and even a phrase like Man's Best Friend which is a colloquial term for a dog could be represented by a vector that's close to the vector for dog on the other hand a word like building is not related in meaning to any of these so its Vector would be much further apart let's say 15 .3 3.9 here's another example that demonstrates how embeddings might capture semantic meaning and relationships between words let's say we have the word King represented by the vector 25 then man is the vector 13 and woman is represented by the vector 14 now let's do some quick Vector arithmetic we'll start with a vector for King then subtract the vector for man to remove the male context and add the vector for woman to introduce new context after performing this Vector math our resulting Vector is 26 so we'll plot that point on the graph and let's say there's another word in our space queen represented by the vector 2 6.2 right here well this Vector is extremely close to the resulting Vector so we might identify queen as the most similar word based on that Vector just as a trained AI model would now a two-dimensional graph is a massive simplification as real world embeddings often exist in much higher dimensional spaces sometimes spanning hundreds or even thousands of dimensions for example the actual Vector embedding for the word Queen might have values across multiple Dimensions each Dimension or number in this Vector might capture a different semantic or contextual aspect of the word Queen for instance royalty Cleopatra or even chess this is what allows the AIS to recognize and differentiate between these contexts when the word is used in different scenarios now imagine embedding hundreds of thousands of words and phrases into this high-dimensional space some words will naturally gravitate closer to one another due to their similarities forming clusters While others are further apart or sparsely distributed in the space these relationships between vectors are extremely useful think back to spotify's method of embedding tracks in a vector space tracks that are positioned closely together are likely to be played one after the other all right so what else can we do with embeddings and how are they used in the real world well you can imagine how embeddings have revolutionized our daily experiences for example search engines have evolved to understand the essence of your queries and content moving beyond mere keyword matching and recommendation systems with the aid of embedding suggest products movies or songs that truly resonate with our preferences and purchase history for example Netflix uses them to create a tailored and personalized platform to maximize engagement and retention also in the healthcare industry embeddings are used to analyze medical images and extract information doctors can use to diagnose diseases and in the finance World embeddings help with analyzing financial data and making predictions about stock prices or currency exchange rates so every time you interact with an AI chatbot every time an app recommends something behind the scenes embeddings are at work translating data into meaning all right so how are these embeddings actually created well let's dive into that next that Lang chain integrates with and if you go to the Lang chain docs and check out modules retrieval Vector stores and Integrations you will see a whole long list of them and by the way this slide is a link through to that page in the docs now for this project we're going to use super base and superbase is a really popular and very userfriendly Vector store but one of the beauties of Lang chain is that it's actually really easy to swap out your vector store so if you want to experiment with various possible Integrations that won't be too much trouble at all now our first task is to set up a superbase account so so head over to superb.com and again this slide is a link to superb.com and let's select start your project and there you can sign up with your email or GitHub and once you've completed the sign up you'll end up at the dashboard so let's go to new project and we need to give the project a name I'm going to call this one scrim bot and we'll also need a database password and I'm just going to allow it to generate a random password password for me and lastly I just need to select my location I'm here in Western Europe not that far from London so that will do just fine then we can scroll down to the bottom and just click create new project now you'll wait a while while it initializes a couple of minutes at the most and eventually you're going to end up here and that shows us that we've got one database successfully set up now if you click on this tables icon on the left hand side here in the table editor tab is where you could manually set up a table but we don't need to do any of that because Lang chain is going to do it all for us if we go back to the Lang chain docs to the super base Integrations page and we just scroll down we get this chunk of code and we're going to run this in our superbase database and it's going to do everything that we need now I've just pasted this code into scrimber just so it's easier to look at and just to be clear we're not running SQL or SQL right here in scrimba we'll be running it in super base and I'll show you how in just a moment but I just wanted to put it right here so we can have a look at it in a bit more detail so what this code does is it enables a PG Vector extension in superbase it then creates our table with everything that we need in that table and it sets the embeddings to 1536 and that's an important number because the open AI embeddings model use 1536 Dimensions it also gives us this match documents function and it's this function which actually does the job of finding the the nearest match so later we'll be using this function to take the vectors from a question and find the nearest vectors from the text chunks because that will identify the text chunks which are most likely to contain the correct answer so all we need to do with this code is copy it go back to superbase and come into the SQL editor tab which is this second one down and paste it right in there now at the moment it's just called Untitled query which is not a great name so I'm just going to change mine to match documents because that's what this main function in it is called now it tells us click run to execute your query so we can do that right here and there we are it says success and if we go to the table editor and we click on documents we can see that we've got our empty table we've got the ID the content the metadata and the embedding I.E the vector and that is what we asked for right here where we said create table documents so that has worked just fine we've got this warning about allowing Anonymous access but don't worry about that right now this is going to be absolutely fine for prototyping now if you'd like to take a deeper dive into vectors and embeddings and exactly what superbase is doing here do check out this blog post that I've linked to right here it's got quite a lot of information okay so now our database is ready to go so in the next Grim let's start getting some vectors into the vector store next which is going to be the knowledge for our chatbot and split it into chunks and the idea is that each chunk will be big enough to hold a piece of information so what you want to avoid is having something like this one chunk where we say we update our course is and a second chunk saying on a regular basis that piece of information needs to be in one chunk else it's pretty much useless now a chunk will often not be that small in fact lots of our chunks are going to hold whole paragraphs so there'll be something much more like that and it doesn't matter at all if there's more than one piece of information in a chunk and in fact that's very likely going to happen all we're trying to achieve here is being able to give an AI Model A smallest chunk of text from which it can find the answer to a question what we could do is just upload a massive document with every request to say the open AI API but that would be very very expensive with tokens so what we're do here is much more economical much more performance and much more scalable okay that's the theory and this is the actual text that we're going to be using for our chatbot it's about 3,000 words long and I've checked and vetted all of the information myself that's really important if the information in the document at the start is faulty you're never going to make a good chatbot now I'm using a text file here for Simplicity but Lang chain has actually got several tools for working with different formats so you can click through to this section in the docs and it will show you options like passing PDF or extracting just the text from HTML to give you just two examples but here we're going to keep it simple and just use a text file so in index.js then I've got this TR catch we're fetching in scrimba dasinfozentrum knowledge source for our chatbot and now we need to split it and we're going to do that using a tool from Lang chain which will do most of the work for us so I've got the Lang chain dependency already installed and in scrimber we do that using a three dot menu that appears when you hover over dependencies you can't see it in the recording but when you click on that three dot menu and select ad dependency a dialog box appears and I can type in Lang chain and it does the rest for me outside of scrimba of course you can use npm install Lang chain okay now Lang chain offers us a couple of tools to split text there is the character text splitter and the recursive character text splitter I'm going to use the latter which is just a little bit more sophisticated but to be honest you can use either and I didn't see a big difference in performance between them in this app so let's import the tool from Lang chain and if you want the more basic character text splitter it's just going to look like that okay let's save a new instance of this recursive character text splitter to a const splitter and then we'll save our output we'll call splitter and use the create documents method now we need to pass create documents an array and inside the array we can list out what we want to be split we've only got one file text but if we wanted to upload to a vector store from multiple files we could list them out in here okay let's just log out the output and see what we get and I'll hit save and then in the console we can just see a promise and that's because this is an async process so we need to await it and there we are as soon as we do that we see our chunks of text and I'm just going to copy one of those chunks and bring it over to Output MD so we can have a look at it so it looks like this we've got page content and that has got the actual chunk of data now it's actually much much long longer than that the scrimba console truncates it heavily and then we've also got the metadata the metadata is quite interesting it gives us the location of that text Chunk lines 1 to 14 so what we're actually looking at if we go back to scrimba info. text is right from the beginning from 1 down to 14 so that is our text Chunk now we W be using this location data in our app but it is good to know for future reference that if you need to refer to where some information came from you have got that information right there provided to you by this text splitting tool now this text splitter that we've used the recursive character text splitter has made some assumptions about chunk size it actually defaults to a th000 characters does chunk size matter well yeah you bet it does larger chunks get more context smaller chunks get more granular semantic info if you go to either Extreme Performance could suffer and if chunks are really big sending that off to the AI models will get expensive now of course there's no best way of splitting and you do have to consider the text you're working with I've experimented a bit and I want to go for a chunk size of 500 not 1,000 so I'm going to come in here with an object and override the default settings so I'll set my chunk size to 500 again we'll hit save and what you can see is where before the first chunk went from lines 1 to 4 14 now we're going from lines 1 to 8 so the chunk is a little bit smaller and I'm just going to use Chrome Dev tools not scribus console to get the text from the first two chunks okay so there we are we've got the first text Chunk and the second text Chunk right here and what you'll notice is that these text chunks are actually split quite nicely into paragraphs this first one ends at a very natural point and this second one does as well and that is not an accident and you'll also notice we've got some overlap here this is a repetition of what we've got right here and again that is not accidental so if we just go back to this object and I can come in here and show you a couple more defaults firstly we have these separators and these separators are an array and they go in order so we've got the double new line to break a paragraph the single new line the space and then no space so what this recursive character text splitter does is actually quite complex it uses those separators to split text into chunks based on the size but prioritizing keeping paragraphs then sentences then words together intact so that's why in these text chunks we've got right here we've got more than one piece of information but that's absolutely fine because they're both contained inside a chunk and they both finish on a natural break and we've got some overlap now we can also override the overlap and it actually defaults to 200 which is quite a lot so I'm going to come in here and this is called chunk overlap and I'm going to set it to 50 so 10% of our chunk size which is a good rule of thumb to start with and you can always experiment now you won't always see overlap and that's because when the paragraphs fit neatly into the chunks and the overlap size is not big enough to include a whole sentence then the overlap won't be applied it will actually only be applied if the chunk size does not end with one of the first two separators so the double new line or the single new line so that is all a little bit confusing and I wouldn't recommend that you worry about it too much do play around with it try different strategies also try the more basic character text splitter and just see which one gets you the best performance with your chatbot and remember you can always come back and adjust it later if necessary now I should just add that if you've got some other separators in your document it's quite popular to use say the double hashtag you can also just add them to this array it does accept custom separators okay I haven't got any of them in our document so I'm going to delete that and the next thing to do then is to take these chunks of text and get them uploaded to the vector store so let's look at that in the next scrim to store and the first thing that I'm going to do is come in here and save our superbase URL and API key to consts and we can get all of the information that we need from the dashboard if you come down here to settings and select API here we have got the project URL and the API key and I've saved mine in my environment variables so I'm just going to come in here and set up the consts and of course you'll need to use whatever you called your URL and API key when you set up your M variable now I'm also going to bring in the open aai API key as we're going to need that in just a moment next I need to set up a superbase client and we do that using the create client method which we get from superbase so before we can use that I need to add the superbase dependency and there we are the superbase dependency has appeared and I'm just going to put the the name of the dependency in a comment just so you can see it a little bit more clearly okay now we've got that superbase dependency we need to import the create client method from it and now we can use create client to set up a client now let's use create client with our URL and API key to set up a superbase client in the final stage of this we do two things at once we're going to create our embedded and we're going to upload them to the vector store to do that we need two tools from nchain the superbase vector store and the open AI embeddings class so let me just import them quickly okay first we're going to use the superbase vector store class so down here I will say await because it does work asynchronously super base Vector store and we're going to use its from documents method and we need to give this method three pieces of information the first one is the output that we've got right here so remember the output is the chunks of text that we've split next we need to tell it how to create our embeddings and we're going to do that with the open AI embeddings that we've just imported so we'll set up a new instance of that class and we just need to pass it at open AI API key which we've got right here now we could pass that as a key value pair like this but as the key and the value are actually the same we don't need to do that we can use the shorthand version Okay the third piece of information is an object holding our superbase details so it needs our client and again we don't need to write out the key value pair we can just use the shorthand version it also needs a table name and if we go back to superbase we can just see that when we go to the tables tab our table name is just documents and just before we run into an error let's remember that this needs to be a string okay let's hit save and see if it works and actually we should have logged something out there with a success message but I totally forgot but now we can go back to our superbase dashboard and I'm just going to come up here to the tables Tab and let's go to documents and we can see it's worked we have got our data we've got the ID the content which is the text for each chunk the metadata and the actual embedding here are our vectors and remember this field is huge we have got 1536 Dimensions here okay now we've got our vectors in our Vector store we can start work on the app that's going to allow us to query this Vector store so when you're ready for that let's go already have over on the right hand side you can see that we've still got our dependencies from Lang chain and superbase now this event listener at the top is listening out for user input so it's basically picking up clicks on this button when a user submits a question we've also still got our API key here that we're bringing in from our environment variable and that just leaves this function progress conversation socalled because it progresses the conversation onwards and also does the heavy lifting of updating the Dom so the user can actually see what response they've got back from the AI now it's all fairly straightforward JavaScript but do feel free to pause and take a look through and also do check out the HTML and CSS if you want to again it's fairly standard stuff okay so that's the code we're starting with so where do we go next with this project well let's head back to the diagram and see where we go first so we take the users input we've got the event listener listening out for that and then we do two things we've got the conversation memory right here and the Standalone question right here I want to focus in on the Standalone question first so let's start by unraveling its Mysteries and see what it actually is and why we want it so we'll come on to that in the next scrim question and just to be clear there are two things we need to do with the users's input they're creating the Standalone question and adding the user's input to the conversation memory now we're actually going to deal with memory at the very end so let's just ignore that for the time being and concentrate in on the Standalone question so what actually is a standalone question well a standalone question is just a question reduced to the minimum number of words needed to express the request for information okay but why do we want one well we can't control control what a user asks our chatbot and actually a user could easily ask a question in a way that's likely to get a vague or even an inaccurate response and we really want to avoid that so imagine you have an online clothes shop and a user asks something like this I'm thinking of buying one of your t-shirts but I need to know what your returns policy is as some T-shirts just don't fit me and I don't want to waste money it's a perfectly reasonable question but let's remember how chatbots work we're trying to find the nearest matching vectors and therefore the chunk of text that will likely hold the answer to our question we want to create an embedding from this question and find the nearest matching vector and therefore the chunk of text that will likely hold the answer to the question in our Vector database but there's so much going on with this question that the vector for it will be polluted remember a vector represents the semantic meaning not the precise words so what we want to do to maximize the accuracy of our chatbot is just extract the intended semantic meaning from this question what we want to focus in on is I need to know what your returns policy is and we can reduce that to a standalone question that will simply be this what is your returns policy that is what the user wants to know and so that is what we need to search for in our knowledge document so that will be our first task and to do that we need to take a look at how prompts work in Lang chain and also how we send them off to the llm the large language model so let's do that in the next scrim chain to set up a simple prompt and just for demonstration purposes we're going to move away from our main project and imagine we're building an app which generates a promotional tweet for a given product we've got the Lang chain dependency already installed right here and of course we're bringing in the open AI API key next we need to to import two things from Lang chain first the chat open aai class and we also need the prompt template class so let's set up our llm and save it to a const so we'll take the chat open AI class and pass in our API key now we could instead pass in nothing and if we do that Lang chain will check process. mv. openai API key and use it if it's available so we could actually delete this line of code as well but to be honest I think it's clear if we just add it manually so I'm going to do it that way and also if we wanted to override any open AI defaults we could do that right here in this object for example we could change the temperature setting so now this llm will use a temperature of 0.5 but to be honest I don't want that I'm just going to leave everything at default for now okay now let's create a template for our tweet and I'm going to save it in a const tweet template and I'm just going to say generate a promotional tweet for a product from this product description and we need to give it a product description so I'm just going to put the product description variable inside curly braces now as soon as you see the curly braces you might think that this is a standard JavaScript template literal it's actually not there's no dollar sign needed here this input variable will be picked up by Lang chain and of course we could have several input variables here if we wanted to if this prompt was going to be a little bit more complex we could also have for example price and anything else we needed but let's just keep this really simple okay now we need to turn this template into a prompt so I'm going to set up a const for the prompt and now we can use the prompt template class and that comes with the from template method and then we just need to pass in our template and before we go any further why don't we just log out the Tweet prompt and see what we've got I'll hit save and we we're getting an error let's just check the console and it says chat open AI cannot be invoked without new okay that's a pretty clear error we needed the new keyword right here let's try that one more time and there we are we've got our prompt and just so we can look at it a little bit more easily I'm just going to bring it into a markdown file and format it okay so we can see that we've got our prompt right here just as we wrote it and the interesting thing is that we've got this input variables property and that is holding product desk so that's telling the prompt which inputs to expect and this is an array so if we had lots of input variables they would just be listed out in this array and now that the prompt is expecting them it's going to throw an error if it doesn't get them another interesting thing to notice here that the template format is an F string and an FST string is something which comes from Python and it is the kind of python equivalent to a template literal okay so that is our prompt ready to go so in the next Grim let's take a look at how we can use it to generate some content template is time to set up our first chain in Lang chain I'll set up a const tweet chain to hold it and what this chain will consist of is our prompt chained to our llm and to join the two parts of the chain together we use the pipe method and I'm going to pass in the llm so the pipe method is joining the two aspects of the chain it takes the output from the first which will be the prompt and it passes it to the llm it's a really simple chain with just one connection again let's just log that out and see what we get and again I'm just going to paste that into our markdown file okay we've got quite a lot going on here but I want to draw your attention particularly to runnable sequence because that is a theme that we're going to be coming back to quite a bit in this course but just by way of an intro what we've got here is a runnable sequence and we can see that this object right here is called First and that is the first element in our chain we've got our prompt right here with our input variables and then we've also got last which is the last section of the chain and here you can see that we have got our open AI llm or large language model now if this were a more complex chain here in the middle we would see some more steps but for now it's just enough to know that this runnable sequence exists okay so if we go back to index.js what we need to do next then is invoke this chain to start the sequence in motion and we're going to do that with a method called invoke so let's set up a response and we need to await our tweet chain because this is an asynchronous process now let's call the invoke method on the chain and we'll just log out the response now if we hit save right now what do you think is going to happen well we're getting an error down in the console it says missing value for input product desk well that figures because look we're expecting an inut variable right here product desk and we're not actually introducing a product description to the chain so what we need to do then is pass in an object right where we invoke the chain so you can think of this as passing something in right to the beginning of the chain and what we need to pass in is a product description so product desk will be our key and then the value will be whichever product we want a tweet for okay let's save that again and down in the console we have got our tweet and in fact we can Zone in specifically on the Tweet by saying response. content and there we are we've got our tweet it's even got some emoji and some hashtags so this is working okay this would be a great time just to pause make sure you understand this code maybe generate a couple of tweets perhaps make this tweet template a little bit more complex with multiple input variables and then when you're ready we'll go back to our main project where we need a prompt and a model and that will give us a great opportunity to have our first challenge so when you're ready for that just move on prompt template and chat open AI already imported we've also got our open AI API key and the llm already set up so here is your challenge I want you to create a prompt to turn a user's question into a standalone question and I've just put a hint here the AI understands the concept of a standalone question you don't need to explain it just ask for it then create a chain with the prompt and the model and lastly invoke the chain remembering to pass in a question and for now we'll just log out the response to check it's working now just to be clear in this challenge we are not going to be wiring this up to the chat interface yet if we were going to do that we would have to actually come down here into this progress conversation function and update some of the logic in here it's a little bit of unnecessary complication at this point we will be coming on to that later also I've given you the four consts that you're actually going to need to complete this Challenge and we're just logging out the response right here I've also given you some hints above each const and I've done that because there is quite a lot of new syntax here and of course you are welcome to go back to that scrim to check the syntax if you need to but hopefully with these hints that might not be necessary now when you do this just remember that the question you pass in should be quite a long- winded question because the idea is to reduce that question down to just the bare minimum so you want to make that a long question with some unnecessary words it's only then that we'll be able to see that it works okay pause now take all the time you need and I'll see you back here in just a moment okay okay so hopefully that went just fine so we'll start off with the Standalone question template this is going to be a string and we're just going to ask for what we want so I'm going to say given a question convert it to a standalone question and then I'm going to say question colon and here I'll use the curly braces and we'll introduce the input variable which is question now I'll invite the model to provide us with the Standalone question by saying Standalone question and just finishing on a colon so that's like an invitation to complete right now we need the prompt so let's set Standalone question prompt equals to prompt template and we'll use the pr template method and pass in Standalone question template then we'll set up the chain so we'll take the prompt that we've just created and we're going to link up the chain with the pipe method and we're piping the llm and remember we've got the llm already set up right here okay to check it's working we need to invoke it and pass in a question so we'll take that chain and this is an async process so we'll await the Standalone question chain call the invoke method and we'll pass in an object we've got the input variable that the prompt is expecting right here it's question and for our question I'm going to go for something quite longwinded I've asked what are the technical requirements for running scrimba I only have a very old laptop which is not that powerful okay we're logging out the response so let's hit save and see what we get down in the console and there we are can a very old laptop meet the technical requirements for running scrimber it's reduced that question down to a standalone question it's just asking for the precise information and it's removed unnecessary words okay that is the first part done so now is a really good time to take a break and relax especially if you've been working at this for a while and when you're ready to go on we're going to look at how we can take our Standalone question to get chunks of matching text from the vector store but there is quite a lot to do that there are several steps in that process and some preparation so for now take a moment to chill and come back when you're ready and see where we are and we are right here so we've taken the users's input and we've created this Standalone question from it and the next step will be to create embeddings from that Standalone question and then take that to the vector store to find the closest match so if we have a standalone question like what is a scrim we'll use the embeddings model to create our vector and then in the vector store we will search through all of the vectors we'll find the closest match and we'll take that chunk of text now this diagram is a little bit of a simplification we might not just take one chunk of text we might take two three even 10 chunks of text and a bit later on we'll look at how we can exert control over how many chunks we retrieve from the vector store okay before we can do any of that we need some basic setup so I've bought in a few Imports here which we've seen before we've got the superbase vector store class I've also bought in the open AI embeddings from Lang chain and create client both of which we used before when uploading to the vector store so those are all of the Imports we need for now and then down here I've set up a new instance of embeddings I've passed in the open a API key do remember that if you don't pass anything in Lang Chain by default will look for process. mv. openai API key in this format and do it for you I'm going to pass it in here manually just for clarity okay we've also got our superbase API key and the superbase URL and we've used that to set up the client and again that is identical code to when we were uploading to the data store okay now things get a bit different to what we did before let's start a new instance of the superbase vector store in a const and and we're going to pass it our embeddings model and we'll also pass it a configuration object in this configuration object we only really need to pass it the client but again just for clarity I'm also going to pass it the table name and our table name in superbase was documents we can see that one right here in the superbase dashboard and I'm also going to give it the query name and again if we look at the superbase dashboard we've got this query match documents which we named after this function match documents so let's pass that in right here so these two are both defaults but I think it's a good idea to put them in here right now because if in the future you're working with a more advanced use case perhaps you've got more than one table or more than one query name it's important that you know that this is where you can configure your vector store okay now this is quite different to what we were doing when we were uploading to the vector store we actually want to retrieve something and without Lang chain we would have to actually write a ton of code to do that but now all we're going to do is create a new const and I'm going to call it Retriever and I'm going to set it equals to our Vector store and I'm going to call the as retriever method on it and that is all we need to do this as retriever method knows to go to the vector store and instead of inserting more data to use the matching documents function that we added here to find the nearest matches so that makes it nice and easy and if you'll remember this match documents query came straight from the Lang chain docks so all of that provided by Lang chain just makes life really easy okay this retriever is now finished and that means it can now be added as an element in a lang chain chain so let's do that next we're just going to come in here down to our chain which we've got right here and we're just going to pipe the retriever on the end so what should now happen is that we invoke the chain and we pass in this question at the top of the chain the Standalone question prompt creates its own prompt from that question it's piped to the llm to get the Standalone question and that should now be piped to the retriever to retrieve the nearest chunks from the vector store well we're logging out the response let's hit save and see what happens and if we open up the console we're getting an error and it's one of those kind of vague errors e. replace is not a function so I think what we should do next is isolate our Retriever and see if it's working so I'm actually going to delete this pipe that we put on the end of this chain and I'm going to set up a second response right here and this is just a test so I'm just going to call it response two and what we're going to await here is our retriever we'll call the invoke method and we'll just pass in a standalone question and I'm going to follow on from this question here and just say will scrimber work on an old laptop okay let's just log out response 2 and see what we get and look we are getting some chunks and we can see that we've actually got four chunks and the first one starts what are the technical requirements so that is looking good for an answer to this question so I'm thinking that our retriever is working just fine so why is it not working in this chain well I think if we log out the original response as well we might see an answer to that question so let's run this again and now we've got quite a lot of data in our console too much to see easily so I'm just going to paste it into a markdown file okay so what we can see is that where we were logging out the original response we have got this object right here and we've got the Standalone question what are the minimum technical requirements for running scrimba can I use it on an old less powerful laptop so that was the Standalone question here we've got our chunks and we've got four of them and that's great so what exactly is the problem if you want just pause for a moment and see if you can figure it out okay so maybe youve figured out that if we have a look at the chain what we're actually doing when we pass things along the chain is passing them along in their expected data type so we

Original Description

LangChain.js is a framework for building AI apps. Click here to get to the course's interactive challenges: https://scrimba.com/links/langchain At the end of this course, you will be able use LangChain's Expression Language to build GPT-powered chatbots that have specific knowledge about an underlying dataset. You will use text embeddings and a vector database to perform retrieval-augmented generation (RAG). The course requires an understanding of JavaScript. Here is a free JS course if you need a refresher: https://scrimba.com/learn/learnjavascript ✏️ If you have any feedback to the teacher Tom Chant, please reach out to him on X here: https://twitter.com/tpchant Also, feel free to follow Scrimba on YouTube: https://www.youtube.com/c/Scrimba ⭐️ Code ⭐️ 🔗 Download via Scrimba: https://scrimba.com/links/langchain ⭐️ Chapters ⭐️ ⌨️ (0:00:00) Introduction ⌨️ (0:02:01) What you'll learn and build ⌨️ (0:04:08) Introduction to LangChain from Jacob Lee (Lead Maintainer of LangChain.js) ⌨️ (0:05:36) App Flow Diagrams ⌨️ (0:09:04) What are embeddings ⌨️ (0:15:20) Supabase Setup ⌨️ (0:19:27) Split the text ⌨️ (0:21:28) Split the text II ⌨️ (0:27:47) Upload to supabase ⌨️ (0:31:53) Starter code ⌨️ (0:33:19) Explainer The Standalone Question ⌨️ (0:35:31) Aside Prompt Templates ⌨️ (0:38:59) Aside Prompt Templates II ⌨️ (0:42:08) Adding the first chain ⌨️ (0:46:11) Retrieval ⌨️ (0:52:45) Add StringOutputParser ⌨️ (0:55:15) Fetching the answer the template ⌨️ (1:00:39) Serialize the docs ⌨️ (1:02:53) Aside RunnableSequence ⌨️ (1:07:54) Aside RunnableSequence 2 ⌨️ (1:10:57) Aside RunnableSequence 3 RunnablePassthrough ⌨️ (1:14:47) Super Challenge - add the RunnableSequence ⌨️ (1:17:10) Super Challenge - solution ⌨️ (1:21:47) Wire up the UI ⌨️ (1:24:34) Setting up the memory ⌨️ (1:27:27) Super Challenge Wire up the memory ⌨️ (1:33:51) Performance Issues Check-list ⌨️ (1:37:44) Outro 🎉 Thanks to our Champion and Sponsor supporters: 👾 davthecoder 👾 jedi-or-sith 👾 南宮千影 👾
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 how to use LangChain.js to build LLM apps with JavaScript and OpenAI. It covers setting up a vector store, creating embeddings, and building a chatbot that can answer questions based on a knowledge document. The video provides a comprehensive introduction to retrieval-augmented generation and conversational retrieval over documents.

Key Takeaways
  1. Create a vector store with knowledge chunks
  2. Split a document into chunks using LangChain's recursive character text splitter
  3. Create embeddings from text data using OpenAI embeddings
  4. Set up a Superbase vector store with embeddings model and configuration object
  5. Create a prompt to turn a user's question into a standalone question
  6. Invoke the chain to get the response
  7. Pipe the prompt to the LLM to get the standalone question
  8. Pipe the standalone question to the Retriever to retrieve the nearest chunks from the vector store
💡 The key insight from this video is that LangChain.js provides a framework for building context-aware reasoning applications, and that retrieval-augmented generation and conversational retrieval over documents can be used to build more accurate and informative chatbots.

Related Reads

📰
RAG Explained Simply: Why AI Gives Wrong Answers (and How to Fix It)
Learn why AI models like ChatGPT give wrong answers and how to improve their performance with RAG
Medium · AI
📰
Retrieval-Augmented Generation: Why Your Brand Needs to Show Up in AI Answers
Learn how Retrieval-Augmented Generation (RAG) impacts your brand's visibility in AI answers and why it matters for marketing and SEO strategies.
Dev.to · Gregory Pellitteri
📰
Where Does RAG Actually Cost You Money? (Episode 2)
Learn where RAG (Retrieval-Augmented Generation) actually costs you money and how to optimize its usage
Dev.to · surajrkhonde
📰
Your RAG system can't answer "why" questions. Here's what you're missing.
Learn how to enhance your RAG system to answer 'why' questions by incorporating causal reasoning and graph-based methods
Dev.to · Marc Newstead
Up next
Build a Chatbot with RAG in 10 minutes | Python, LangChain, OpenAI
Thomas Janssen
Watch →