تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Introducing RAG Basics0:00

Rag, or RAG, sounds kind of complicated, it sounds fancy, but in practice, it's really quite simple. We simply embed our data, and then we search by meaning. Rag stands for retrieval augmented generation. We retrieve relevant data from our app. We augment the prompt with that data. And then we generate a response grounded in real data sources. And this matters because, you know, large language models are great at language. I mean, there's no question about that. But they are weak at specific current facts, especially facts that,

there's no question about that. But they are weak at specific current facts, especially facts that, really, it doesn't have, because what we want to do is use our data. And, you know, the model doesn't have our data. So, RAG gives us the ability to use a model and to keep answers grounded in our data, so that the model just doesn't have to guess. And so, then the question is, what is embedded data? Basically, it's just a numeric fingerprint of our data. And that's it. And what

Embeddings and Similarity1:10

what is embedded data? Basically, it's just a numeric fingerprint of our data. And that's it. And what we are going to do is build a search so that we can find data based upon our query. But the way that we are going to do it uses embedded data with embedded data, a data that's close or data that is similar to each other are closer together. Data that's not similar are farther apart. And, you know, before we go any farther, I should say that I'm using SQL light, which doesn't

And, you know, before we go any farther, I should say that I'm using SQL light, which doesn't have a vector column type. There are some databases that do like Postgres. And when it comes to working with embedded data, we essentially have to use cosine to find, you know, the similarities between two sets of embedded data. So, if this is a feature that you want to implement within your application, you need to use a database that has vector column types, just because it's much

Building Cosine Helper2:07

application, you need to use a database that has vector column types, just because it's much more efficient. And it scales very well. What we are going to use is just a JSON column. And we will have a helper class to, you know, do our calculations for us. So it's going to work. It's not going to work as well as if we had a database that would support it. So we're going to start with that helper class. Let's create a new file. This is inside of app support. And I'm

with that helper class. Let's create a new file. This is inside of app support. And I'm going to call it vector dot PHP. And I'm not going to type this out. I'm just going to paste it in, because it's it's ultimately something that's we can easily find anywhere online. The idea here is that we want to calculate the cosine similarity between two vectors. So we're going to end up with a value that's between zero and one, or one point zero. Of course, the closer that the

end up with a value that's between zero and one, or one point zero. Of course, the closer that the result is to zero, the more dissimilar the two vectors are, the closer we are to 1.0, the more they are identical. So that's the range. And when you think in terms of search, you know, unless if we just get really lucky, and our search term is very close to, you know, the title of a document, or even the body of a document, then it's going to be, you know, close to one. In most cases, we

or even the body of a document, then it's going to be, you know, close to one. In most cases, we are going to be closer to the zero side. So we need to take that into account, because well, let's just say that we have a title of billing and refunds. That's the title of a document. And if we search for refunds, well, yes, refunds is here. But in the grand scheme of things, if we are comparing these two complete sets of data, they are dissimilar. There is some similarity, but it's small, maybe 30%,

two complete sets of data, they are dissimilar. There is some similarity, but it's small, maybe 30%, maybe 40% similar, in which case, that would be, you know, considered a hit, basically, whether there is a hit for our search of refunds. So that's kind of how we have to think about this because in order to get closer to zero, we would have to have billing refunds, or I'm sorry, closer to one, we would have to have billing and refunds together. So that's we would be closer there. Anyway, this

Creating Search Controller4:36

would have to have billing and refunds together. So that's we would be closer there. Anyway, this is what we are going to use to compare the two vectors. And again, it's going to work for us. Ideally, we would have a vector column so that the database could do it for us. The next thing we need is a controller. And you know, we don't typically need a controller in this particular case. Maybe it would be a service so that we can extract that into a service. And then we could use it

Maybe it would be a service so that we can extract that into a service. And then we could use it inside of a controller or inside of a live wire component or inside of any other thing that we would want. But to keep things just a little more simple because this, the overall idea is simple. The implementation is a little involved. So we're just going to stick with the controller because that makes things a little more simple. So the first thing that we are going to

controller because that makes things a little more simple. So the first thing that we are going to start with is our user, which we will get from the request. We also need to know the team that the user is a member of. So we will use current team ID there. And then we need to know the query. What is the user trying to find? So we will get that from the request. It's a string. We'll use the query parameter of Q. And we will trim that so that then we need something to store

use the query parameter of Q. And we will trim that so that then we need something to store our document results. And we'll just create a collection there. And then finally, we need to set a minimum threshold to filter the results. And this goes back to, you know, what the resulting calculation is going to be. It needs to be closer to zero because we'd have to be really lucky to get, you know, something closer to one. So we're going to call this min

be really lucky to get, you know, something closer to one. So we're going to call this min similarity. And I think a good place to start is 30%. We might need to lower that. But I think 30% is at least a good place to start. So that now we will check if query is not empty, then we want to perform our search. And the first thing that we need to do is embed the query information, because we need that vector of the query so that we can compare it

embed the query information, because we need that vector of the query so that we can compare it to the vector of the document that we are searching for. So this is where the SDK comes into play, because we have this embedding class, and we will use it to generate the embed ding data for in this case, the query. And we want to generate that. And we want the first. So let's talk about this, this embeddings class still is going to use the AI model. But

first. So let's talk about this, this embeddings class still is going to use the AI model. But the question then becomes what AI model is it going to use? So if we go back to our config for the AI, you know, right here, we have caching, and we have caching and embeddings and the cache and all of that stuff. But that doesn't tell us anything. We need to scroll up here so that we can see the defaults. Default is open AI for images, it's Gemini for audio, it's open AI. But here

the defaults. Default is open AI for images, it's Gemini for audio, it's open AI. But here default for embeddings is open AI. So our config is already set up to use open AI to generate these embeddings for the query, in this case. But we are also going to create the embedded data for the documents. Now this is something we haven't talked about, we have a documents table, we just haven't used it before, and we have an ID, we have the team ID, the title of the body. But

just haven't used it before, and we have an ID, we have the team ID, the title of the body. But we have a JSON column for the embedding data. And we can see that it's all null right now. And that doesn't necessarily help us because we need that embedded data so that we can compare it to, you know, the query embedded data. So basically what we need to do is iterate over all of the documents and generate this if it's not already there. So we will do that by getting the documents

documents and generate this if it's not already there. So we will do that by getting the documents where the team ID is the team ID that we retrieved before, and then we want to get those documents. Although where's team? Oh, team ID. There we go. Let's go ahead and pull in our document model. And then we want to get to the results of the calculation between the document embedded data and the query. So we are going to map over our documents. We want to work with each document.

data and the query. So we are going to map over our documents. We want to work with each document. We want to use the query embedding. So that first of all, we will get the embedding from the document using that embedding attribute. Now, of course, as we saw, embedding is null. So if embedding is not an array, then we need to generate the embedding data for that document. So we will use the embedding's class for the data that we want to embed, which in our case will be the

will use the embedding's class for the data that we want to embed, which in our case will be the document title. And we also want the document body, because we want to search based upon those two values. It only makes sense to do that. So we will generate and get first, and then we will update the document, setting the embedding column to the embedding value. And this is important because now we will be caching that inside of the database. So any other subsequent search is going

because now we will be caching that inside of the database. So any other subsequent search is going to be just a little bit faster, because all of that's going to be done. And we can just go on to calculating the difference between the two vectors. But of course, we're not done yet. We are still inside of map, we want to get the score of each document compared to the query. So our result set is going to be the document, and then the score of the cosine between the query embed

result set is going to be the document, and then the score of the cosine between the query embed ding and the embedding from the document. So document results is going to contain an array where it has the document, and then the score comparing the document to the query. But remember, we want to filter the results based upon, you know, the similarity here. So we want to filter these results, so that the result score is greater than or equal to the min similarity, we then want to

Adding View and Routes11:21

so that the result score is greater than or equal to the min similarity, we then want to sort by descending score, so that we can take five, and then we want just the values. So that then , once we have all that, we want to return the view for AI dot, let's call this knowledge search. And then we want to supply various things, we want the query, which will be the query to string, we also want the document results based upon the document results. Let's also include the min

also want the document results based upon the document results. Let's also include the min similarity, so that we can display that in the view as well. And that's going to be that for this document search. So let's create a new view, and we will create a new file called knowledge search dot blade dot PHP. And I'm going to paste that in because that's a lot and there's nothing special about this markup. All it is is a form for searching and then providing the output of that search. We do,

this markup. All it is is a form for searching and then providing the output of that search. We do, however, need to set up a route. So let's open up web dot PHP so that we can set up a route for this controller. But then if we take a look at the UI, we need a link to take us to our AI search. So let 's open up the sidebar dot blade dot PHP, we have the dashboard, we have the tickets after the tickets. I'm going to paste in for our AI search. So with that in place, we can go to our AI

Testing Semantic Search12:58

tickets. I'm going to paste in for our AI search. So with that in place, we can go to our AI search, and we can perform a search. If we search for refund, we are going to get some results, we 'll get at least one. Hopefully, if everything works, okay, and sure enough, we did now notice the similarity, the similarity is just a little bit over 30%. And that's okay, because, you know, as I said, in order for this to be closer to one, we would have to have an exact match between the

as I said, in order for this to be closer to one, we would have to have an exact match between the title and the body. So even if we search for the exact title, the similarity is going to be more, but it's still, well, it's 68%. So we're a little bit there. By using embedded data, we now have a semantic search that searches across all of our documents. And we can expand this to our tickets as well, if we wanted to. Our tickets don't have an embedding column, but we could easily add

tickets as well, if we wanted to. Our tickets don't have an embedding column, but we could easily add that and then include the ticket data in the search. But the important thing is that we are using AI to help us search our own data. And I think that's pretty cool.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟