Semantic search ranks results by meaning: the query and every document become vectors, and the documents whose vectors point closest to the query's come first.
An embedding model turns text into vectors, and those vectors are called embeddings.
Embed the query with the same model you used for the dataset, because vectors from two different models can't be compared.
Cosine similarity scores two vectors by the angle between them. With text embeddings the scores almost all fall between 0 and 1, and higher means more similar.
Split your text into chunks that fit the model's token limit (512 tokens for gte-large), and store the embeddings so you only generate them once.
Semantic search finds results by what your query means instead of the exact words in it. It turns your query and every document into vectors with an embedding model, then ranks the documents by how closely their vectors point in the same direction as the query's.
That's how a search for "fantasy movies" can return Lord of the Rings and Harry Potter, even though neither title has the word "fantasy" in it. Below I go through keyword search, vectors, embedding models and cosine similarity, then the full pipeline, and then a working movie search in Python. The video above covers the theory if you'd rather watch.
Keyword search vs semantic search
Keyword search matches words. Does this title or document contain the words in my query? If it does, it's a result. Search engines build an index from every word to the documents that contain it, so the lookup is fast and you can always see why something matched.
That works until the words don't line up. Search a movie database for "fantasy movies" with keywords and you'll get films with "fantasy" in the title or description. Lord of the Rings and Harry Potter don't say "fantasy" anywhere in their names, so you can't tell from the titles alone.
Semantic search matches the meaning behind the words. It knows "fantasy" has to do with magic and quests, and it knows Lord of the Rings is about a quest with wizards in it, so the two come out close together.
Keyword search
Semantic search
Matches
The exact words in the query
The meaning of the query
"fantasy movies" finds Lord of the Rings?
Only if the text says "fantasy"
Yes
How it ranks
How often and where the words appear
How similar the vectors are
What it needs
A word index
An embedding model and somewhere to store vectors
Good at
Exact names and error codes
Plain-language questions and synonyms
Keyword search still wins when someone types an exact product code or a person's name, which is why a lot of real search systems run both and merge the results (usually called hybrid search).
Words as vectors
Picture every word as a point on a map. "King" and "queen" mean similar things, so they sit close together. "Solar system" is a different concept entirely, so it sits far from both, near words like "Mars" and "Earth". Semantic search builds that map, and once you have it, "fantasy movies" lands near Lord of the Rings and Harry Potter.
Under the hood, those points are vectors: quantities with a magnitude and a direction, like the arrows from maths or physics class. Six feet tall is only a magnitude. A vector also points somewhere, and for search the direction is what matters. "King" and "queen" point almost the same way while "solar system" points somewhere else, so to check whether "fantasy" and "Lord of the Rings" are related, you check whether their vectors point the same way.
Real models use hundreds or a thousand numbers per vector, not two. The model I use below produces 1,024. You can't draw that, but the maths works the same as with arrows on paper.
Embedding models turn text into vectors
"Fantasy" is an English word, not a vector, so something has to convert it. That's the job of an embedding model: a machine learning model whose only purpose is to turn text or images into vectors.
The one I use most is thenlper/gte-large on Hugging Face. Hugging Face is a site full of AI models and datasets, and if you're doing anything with AI or machine learning, you should be on it.
You give the model text and it gives you back vectors, which are called embeddings. When someone says "embeddings", they just mean vectors that came out of an embedding model.
Cosine similarity ranks the results
Knowing two things are related isn't enough. If I search for "fantasy movies", should Lord of the Rings come first or Harry Potter? Obviously Lord of the Rings, because it's the better movie, but the search engine needs a number.
Because embeddings are numbers, you can run formulas on them, and the usual one is cosine similarity. It measures the angle between two vectors and ignores how long they are. Two vectors pointing the same way score 1, and the further apart they point, the lower the score. In theory it goes down to -1. With text embeddings the scores you see in practice almost all fall between 0 and 1, and higher means more similar.
So you score the query against every document and put the highest score at the top of the page. Euclidean distance (the straight-line distance between the two points) and the dot product also work, but cosine similarity is what I reach for in most cases.
The semantic search pipeline, step by step
Searching your own data by meaning takes two stages: you prepare the data once, then you answer queries as they come in.
Preparing the data:
Load your dataset, whether that's documents or rows from a database.
Convert it to text. Embedding models take text, so you can't pass in a database table as it is.
Clean it up and split it into chunks that fit the model's token limit.
Run every chunk through the embedding model.
Store each chunk's embedding next to the item it came from, so you never have to compute it again.
Answering a query:
Embed the user's query with the same model you used for the dataset. Vectors from two different models can't be compared, even when they're the same length.
Compute the cosine similarity between the query's embedding and every stored embedding.
Sort by that score and show the top 10 or 20 results.
Chunk your text to fit the token limit
Every embedding model has a maximum input length, measured in tokens. Some take 1,024 tokens and some take 512 or fewer. gte-large takes 512. Put in more than that and you get bad embeddings, or the model cuts the text off without telling you (that's what the sentence-transformers library does). Check the limit in the model's documentation and chunk your text to fit.
Store your embeddings
Generating embeddings is slow. I once generated about 50,000 of them for a project and it took around four hours. You never want to do that every time your program starts, so save them.
Embeddings are vectors, and there are databases built to store and search vectors: Pinecone, Chroma, pgvector (a Postgres extension) and Weaviate. For a small project, a file on disk is fine, and that's what the code below does.
Build a semantic movie search in Python
When I made the video I said I'd implement this in code in a later one. Here it is in writing instead: a movie search over the plots of 34,886 films, using the pipeline above. The same code is in my semantic-search repo on GitHub, with setup steps for uv.
The data is the Wikipedia Movie Plots dataset on Kaggle. Download it and put wiki_movie_plots_deduped.csv in a data folder.
Install sentence-transformers, which pulls in PyTorch and downloads models from Hugging Face for you:
pip install sentence-transformers
If you're on Linux without an NVIDIA GPU, install the CPU build of PyTorch first with pip install torch --index-url https://download.pytorch.org/whl/cpu. The default one bundles a few gigabytes of CUDA libraries you won't use.
The project looks like this:
semantic-search/
├── main.py
├── data/
│ └── wiki_movie_plots_deduped.csv
└── cache/
└── embeddings.pkl (created on the first run)
Here's main.py:
import csv
import os
import pickle
import re
from dataclasses import dataclass
import torch
from sentence_transformers import SentenceTransformer
MODEL_NAME = "thenlper/gte-large"
# MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
DATASET_PATH = "data/wiki_movie_plots_deduped.csv"
CACHE_PATH = "cache/embeddings.pkl"
@dataclass
class Movie:
release_year: int
title: str
origin: str
director: str
cast: str
genre: str
plot: str
def load_model() -> SentenceTransformer:
# Half precision is fast on a GPU but very slow on a CPU
if torch.cuda.is_available():
return SentenceTransformer(MODEL_NAME, device="cuda", model_kwargs={"dtype": torch.float16})
return SentenceTransformer(MODEL_NAME, device="cpu", model_kwargs={"dtype": torch.float32})
def load_dataset(file_path: str = DATASET_PATH) -> list[Movie]:
movies = []
with open(file_path, encoding="utf-8") as csvfile:
for row in csv.DictReader(csvfile):
movies.append(Movie(
release_year=int(row["Release Year"]),
title=row["Title"],
origin=row["Origin/Ethnicity"],
director=row["Director"],
cast=row["Cast"],
genre=row["Genre"],
plot=row["Plot"],
))
return movies
def divide_into_chunks(text: str, chunk_size: int = 3, overlap: int = 1) -> list[str]:
sentences = [s.strip() for s in re.split(r"(?<=[.!?])\s+", text) if s.strip()]
chunks = []
step = chunk_size - overlap
for i in range(0, len(sentences), step):
chunks.append(" ".join(sentences[i : i + chunk_size]))
if i + chunk_size >= len(sentences):
break
return chunks
def convert_to_text(movie: Movie) -> list[str]:
# Every chunk repeats the movie's details, so each one makes sense on its own
chunks = divide_into_chunks(movie.plot) or [""]
return [
f"Title: {movie.title}\n"
f"Year: {movie.release_year}\n"
f"Director: {movie.director}\n"
f"Cast: {movie.cast}\n"
f"Genre: {movie.genre}\n"
f"Origin: {movie.origin}\n\n"
f"Plot ({i + 1}):\n"
f"{chunk}"
for i, chunk in enumerate(chunks)
]
def load_or_create_embeddings(movies: list[Movie], model: SentenceTransformer) -> dict:
if os.path.exists(CACHE_PATH):
print("Loading embeddings from cache...")
with open(CACHE_PATH, "rb") as f:
return pickle.load(f)
texts = []
metadata = []
for movie in movies:
for i, text in enumerate(convert_to_text(movie)):
texts.append(text)
metadata.append({
"title": movie.title,
"year": movie.release_year,
"genre": movie.genre,
"director": movie.director,
"chunk_index": i,
})
print(f"Embedding {len(texts)} chunks from {len(movies)} movies...")
embeddings = model.encode(texts, batch_size=64, show_progress_bar=True, convert_to_numpy=True)
data = {"embeddings": embeddings, "texts": texts, "metadata": metadata}
os.makedirs(os.path.dirname(CACHE_PATH), exist_ok=True)
with open(CACHE_PATH, "wb") as f:
pickle.dump(data, f)
return data
def search(query: str, model: SentenceTransformer, embedding_data: dict, top_k: int = 200) -> list[dict]:
# The query goes through the same model as the dataset
query_embedding = model.encode(query, convert_to_tensor=True)
corpus_embeddings = torch.tensor(embedding_data["embeddings"], device=query_embedding.device)
scores = torch.cosine_similarity(query_embedding, corpus_embeddings, dim=1)
top_results = torch.topk(scores, k=min(top_k, len(scores)))
results = []
for score, idx in zip(top_results.values, top_results.indices):
idx = idx.item()
results.append({
"score": score.item(),
"text": embedding_data["texts"][idx],
"metadata": embedding_data["metadata"][idx],
})
return results
def display_search_results(results: list[dict], limit: int = 20):
# One movie can match with several chunks, so show each movie once
seen = set()
for result in results:
meta = result["metadata"]
if (meta["title"], meta["year"]) in seen:
continue
seen.add((meta["title"], meta["year"]))
plot = result["text"].split(":\n", maxsplit=1)[-1].replace("\n", " ")
if len(plot) > 200:
plot = plot[:200] + "..."
print(f"{len(seen)}) {meta['title']} ({result['score']:.4f}) [{meta['genre']}, {meta['year']}, {meta['director']}]")
print(plot)
print()
if len(seen) >= limit:
break
def main():
movies = load_dataset()
print(f"Loaded {len(movies)} movies.")
model = load_model()
embedding_data = load_or_create_embeddings(movies, model)
while query := input("Search (blank line to quit): ").strip():
display_search_results(search(query, model, embedding_data))
if __name__ == "__main__":
main()
load_model() loads gte-large on the GPU if you have one. On a CPU it asks for full 32-bit precision, because the current version of sentence-transformers loads this model in half precision, which runs many times slower on a CPU.
divide_into_chunks() splits a plot into sentences and groups them three at a time, with one sentence of overlap so the context carries from one chunk into the next. convert_to_text() puts the movie's title, year, director, cast and genre on top of every chunk. So a chunk from the middle of a plot still knows which movie it belongs to.
load_or_create_embeddings() is the preparation stage. If cache/embeddings.pkl exists, it loads that. If not, it embeds every chunk in batches of 64 and pickles the vectors to disk along with each chunk's movie details.
search() is the query stage. It embeds the query with the same model and scores it against every chunk with torch.cosine_similarity. Then torch.topk picks the 200 best, which is faster than sorting the whole list. A long plot gets many chunks, so one movie can take several of those 200 spots. display_search_results() skips repeats and prints up to 20 different movies.
Run it
python main.py
The first run downloads gte-large (about 670 MB), then embeds every chunk and saves the result to cache/embeddings.pkl. After that, it loads the file and goes straight to the search prompt.
That first run is slow without a GPU. The whole dataset comes to 328,648 chunks, and on my laptop's CPU gte-large embedded fewer than two chunks a second, which works out to more than two days. On a machine with an NVIDIA GPU the code uses the GPU on its own, and Google Colab has free GPU runtimes if you don't have one. On a CPU, switch to the commented-out all-MiniLM-L6-v2 line. It's a much smaller model (384 numbers per vector and a 256-token limit) that ran about 20 times faster in my test, at some cost to the results. I tested this code on 350 of the movies (4,868 chunks), and with gte-large that took 46 minutes on the same CPU.
Delete cache/embeddings.pkl whenever you change the model or the data, or you'll be searching stale vectors.
Here's the top of what I got for the query from the video (I've cut the plot line under each result):
Search (blank line to quit): fantasy movies
1) The Lord of the Rings: The Two Towers (0.8742) [adventure, fantasy, 2002, Peter Jackson]
2) The Chronicles of Narnia: Prince Caspian (0.8737) [fantasy, 2008, Andrew Adamson]
3) The Lord of the Rings: The Return of the King (0.8718) [adventure, fantasy, 2003, Peter Jackson]
4) The Lord of the Rings: The Fellowship of the Ring (0.8717) [fantasy, 2001, Peter Jackson]
5) The Sorcerer's Apprentice (0.8677) [adventure, comedy, fantasy, 2010, Jon Turteltaub]
6) The Lord of the Rings (0.8671) [fantasy, animated, 1978, Ralph Bakshi]
Lord of the Rings on top, as it should be. That query only printed 15 movies, because the Lord of the Rings and Harry Potter films have long plots and filled most of the 200 best chunks between them.
The genre field helps with that query, since it literally says "fantasy". Queries that don't name a genre show the difference better. "A wizard school" put Harry Potter and the Sorcerer's Stone first. "A man stranded alone on another planet" put The Martian first, and Cast Away and Interstellar both made the top four.
Further down that list the results drift into movies that have little to do with the query. Semantic search always returns its closest matches, even when nothing is close, and a 350-movie slice doesn't have many films about being stranded. The score tells you how close each match is, so in a real app you'd cut results off below a threshold.
Why this is worth learning
This is how Google gives you decent results when your words don't match the page, and it's how RAG apps find the right documents before an LLM writes its answer. Under all of it are vectors and the angles between them.
I only learned this properly a month or two before I made the video, and I still find it fascinating. What looks like a search engine reading your mind is a model turning text into arrows and a formula checking which ones point the same way. Technology is beautiful once you understand how it works.
Video transcript
ShowHide
Have you ever wondered how, if I search for fantasy movies on Google, it's going to recommend me things like Lord of the Rings, Fantastic Beasts, Harry Potter, or something like that? Even though the names of these movies don't necessarily have the word fantasy in them, how does Google know that these movies are related to fantasy or adventure or stuff like that, right?
You obviously can't use keyword search for this because none of the keywords would match, right? Who says that these are fantasy movies? You can't tell them from their titles alone, right? So, how does Google know what fantasy even means? What do I mean when I say fantasy movies, and how does Google know that these movies match that criteria, right?
Well, it's something called semantic search. Let's talk about that.
Semantic search is the complete opposite of keyword search. In keyword search, let me just type all of these things out as well so you can talk about them. In keyword search, we're basically, you know, matching keywords, right? Does this word, or does this title, a movie, or text have or contain the words in my search query? If yes, then we return those results, right?
But obviously, keyword search is not going to match things like fantasy movies and Lord of the Rings, right? That's where semantic search comes in. Semantic search is going to match the meaning behind the words, right? The actual meaning, what the words mean, right?
So, as an example, if you have two words over here, like if you have two words like king and queen, notice how much similar they are to each other, right? And that is why I've placed them similar over here. And notice the word solar system. You can probably tell king and queen are very similar to each other, but the word solar system, that's just a completely different concept, right? And so that is why it's so far away from these two words.
That's what semantic search does. It clusters together similar words like this. It clusters together words with similar meaning so that they're, you know, closer together. And as for the words that aren't really similar to each other, it's going to move them far apart like this.
Solar system word over here, this solar system is going to have similar words like, I don't know, Mars or Earth or the Sun. It's going to have those kinds of words similar to it, right over here, close to each other, right? But it's going to be far away from words like king and queen, right? Because they're just not similar to each other.
That's how semantic search works. It basically just clusters together similar words so that we can actually infer the meaning of those words. So that if I search for something like fantasy movies, movies like Harry Potter, Lord of the Rings, Fantastic Beasts, they're going to be similar to fantasy movies, the words, right? And that is why I get them in the search results.
Now, that's a very general, high-level overview, right? That's something that even Google could tell you. How does this thing work under the hood, right? Let's talk about that.
And the big thing here is basically vectors, right? If you've studied vectors, like maths and physics before, you know what I'm about to talk about over here. But basically, vectors are quantities that have both a direction and a magnitude, right?
So, for instance, you can have a value with just a magnitude, like six feet tall or six figures income or, you know, stuff like that. But when you have a vector, you have both a quantity, that's the magnitude, right? That's how big this thing is, right? Now, this could be six inches, this could be 12 inches, this could be nine inches, and it also has a direction. So right now, it's pointing over here, or it could point over here or wherever, right?
Vectors are used everywhere in the machine learning and, you know, natural language landscape, right? Every single machine learning algorithm you use, there's a high chance that they're using vectors, right? All the neural networks, all the machine learning algorithms and models out there, they're using vectors to model their data, basically.
So you could have a vector over here that says king. You can have a vector over here that says king, queen, something like that. Let me just label these as well for you. So this is how you would represent the same thing I drew over here for you in terms of vectors, right?
You can see that the king and queen vector are very similar. They have a very similar direction. They have similar magnitudes as well. As for the solar system vector over here, it has a much different magnitude, and it has a completely different direction as well.
That is why we use vectors in machine learning and neural networks because of their direction property, right? You can see how similar two vectors are by their direction. Since king and queen are two similar words, they have almost the same direction over here, right? They're pointing in the same direction. That is not the case for the word solar system. It's pointing in a completely different direction because these words are not similar, right?
So we use vectors for their direction property because the vector direction allows us to tell how similar two vectors are.
So we want to know how Google is able to implement semantic search to tell you that Lord of the Rings is a fantasy movie. This is how. It has something like the word fantasy over here, and then it has something like Lord of the Rings over here. And because these two vectors have almost the same direction, Google knows that they're similar.
So Google knows that when you're searching for fantasy movies, you're asking for Lord of the Rings and other movies like that, right?
So now the question becomes, how do you convert words into vectors, right? Because fantasy, solar system, these are just English words, right? How do you convert these English words into their mathematical vector representation? That's where embedding models comes in. So let's talk about that.
Let's talk about embedding models. Embedding models are a special kind of machine learning model whose entire purpose is to convert text or images or other kinds of data into vectors, right?
Let me actually show you an example of a model that I often use. This is, I don't even know how to pronounce this, but `thenlper/gte-large`, right? This is an embedding model that's going to convert any text that you give it into a bunch of vectors, right? And this is on Hugging Face. Hugging Face is basically just a website that has a bunch of AI models, data sets, and other things.
It's a really great website to be on if you're developing AI and machine learning stuff, right? If you're working in this field, you need to be on Hugging Face or Kaggle or other websites like that.
But basically, embedding models are just a bunch of machine learning models that take some sort of text. Let me actually draw something out over here, like a flowchart, so you guys understand. So this is what embedding models do. You have some sort of input text. You can also have images, by the way. We'll get to that. You have some sort of input text or images that you want to convert to vectors. You pass those into an embedding model, which is just a machine learning model that's used to convert text or images into vectors, into their mathematical representation. And then this model is going to output a bunch of embeddings.
Embeddings is the word we use to represent these vectors. So anytime someone says embeddings, they mean vectors, right? They just mean vectors, just like what we have over here, but they just mean it in the context of embedding models and semantic search, right? That's what embeddings mean. They just mean a bunch of vectors.
All right. Now, once we have these vectors, we've converted our input text into a bunch of embeddings, into a bunch of vectors. That's when we can actually check their vector direction, and we can tell whether this is similar or not, right? We can tell if we search for fantasy, whether that is similar to Lord of the Rings or not, because now we have their direction, right? And then we can return the appropriate search results. That's how semantic search works.
Okay, so now we know how to check whether two things are similar, right? Now, how do we check how similar they are? How do we rank these search results? So there is a visual way of doing this. Let me add a couple more arrows over here. Let's say something like, I don't know, Harry Potter, right? That's a kind of a fantasy movie as well. How do you rank these search results? Which one of these should come first, right? Which one, if I search for fantasy movies on Google, should Lord of the Rings come first or Harry Potter? Well, obviously Lord of the Rings because that's a better movie. But how would Google know that, right?
Well, again, the benefit of representing these things as vectors, as mathematical quantities, is that we can do all sorts of mathematical formulas and computations on it. One such formula is called cosine similarity, and I'm not going to go too deep on this, but basically, it's a formula, a mathematical formula that you can use on vector quantities. You can run the numbers on this, and you can tell how similar two vectors are, right?
So if you calculate this, then let's say Lord of the Rings is more similar to the fantasy, the fantasy vector over here, and so that's going to be the top result of the search page, right? And then let's say Harry Potter is not as similar as Lord of the Rings, so it's going to be the second search result on the page, right? That's how cosine similarity works, and this is, I guess, the most popular way to calculate vector direction and rank the results, right? There are others as well, but we're not going to go too deep on them.
What you need to just understand is that we have a bunch of vectors. These are just mathematical quantities, and since they're mathematical quantities, we can run all sorts of formulas and calculations on them to tell which vectors are similar to each other and how similar they are. We can then use these mathematical formulas to rank the search results, right? So, for instance, this cosine similarity is going to give us a search score, a ranking score between 0 and 1, and whichever of these search results has the higher score, obviously, we're going to put that on top of the search results, right? That's how that works.
So, on a high-level overview, that is how semantic search works, right? You have a bunch of text. You embed that text using some sort of an embedding model over here, and you generate the embeddings, which are just vectors under the hood, right? Then you use mathematical formulas like cosine similarity, like Euclidean distance, and like a bunch of other formulas to tell which vectors are more similar than others. And then you use those scores, those formula answers, to rank the search results and show the most similar search results at the top, right? That's how semantic search works.
And I also have a little, you know, flowchart over here to really describe the entire process. By the way, we're going to implement this in code as well in a future video, probably the next one after this. I'm going to implement semantic search in code so you can actually see how it works. But first of all, this is like an entire overview of how to handle semantic search in your own database, right?
So let's say you have a big database of text or documents that you want to be able to search through using semantic search, using meaning, right? This is how you would do it. You would first of all prepare the model. That's stage one. And to do that, you load your data set, which is a bunch of documents or databases or whatever. You convert it into text. You know, you can't just pass in a database table or some other stuff like that. You need to convert it into text because these embedding models are designed to take text as input, right?
So you convert your data set into a bunch of text, you pre-process it, and that just means cleaning up the data a little bit. You break it into chunks, and the reason you break it into chunks, and I forgot to discuss this, is because each of these embedding models has some sort of a token limit, right? They have a token limit over here, and this is different for every single model, right? So some models have a 1,024-token limit, some have a 512-token limit, some have even less than that. And basically, what this means is how many words can you input into this model and get some really high-quality embeddings generated by that? If you put too many tokens in, you're gonna get some really horrible results from that, right? So every single model has a token limit, and you can read about this in the model's documentation page.
Right, wherever you download the model from, from Hugging Face or something like that, they have this information in their documentation, and you can read that. But yeah, every single model has a maximum token limit, and you need to stick within that token limit. And that is why you need to break your text into chunks that can fit into the model's token limit, right?
And then you use the AI embedding model to encode your text and generate the embeddings for it, right? Once you've generated the embeddings, you have the vectors. Then what you're going to do is you're going to store that embedding data alongside the data item that you've got, right? So if you add some sort of a document that you're embedding, you want to store the embeddings that you've generated alongside that data so you can reference them easily later, right?
And also, embedding is a very expensive process computationally. It takes a lot of time to generate embeddings for text, especially if you're using a good, decent model, right? So you need to make sure that you store the generated text, so store the generated embeddings in some sort of a cache file or a vector database so that you don't have to recalculate them.
The best place to store this is because, look, embeddings are just vectors, right? There are vector databases you can use out there, things like Pinecone, things like ChromaDB, things like pgvector, which is a plugin in Postgres, things like VV8. These are vector databases, and they are specifically designed to store vector quantities, right? So you should use something like that, or you can even literally store them in some sort of a binary file on your disk, right? We're going to go through that as well in the next video, but you want to store them in some sort of a database or a file so you don't recalculate them every single time you run your program because this is a very computationally expensive process.
I literally generated like 50,000 embeddings yesterday for one of my projects, and it took like four hours, right? So you need to make sure you cache them somewhere, right? So you don't recalculate them.
Once you've done that, you're basically done with preparing the model, right? You're basically done with stage one, which is just preparing the model. Now you can actually handle search queries. And the way you do that is you take the user search query, like let's say I search for something like "fantasy movies" again or something like that. You take that query and use the same embedding model that you used to generate an embedding for my search query as well, right?
You're going to convert my search query, like "fantasy movies", into its embedding form, into its vector representation. So now you have your search query and you also have your data set, both of them as vectors, right? As embeddings. Then you're going to compare the cosine similarity of the query embedding, which is what I search, with each item's embedding in your data set, right?
And again, you can use cosine similarity, you can use other formulas, but cosine similarity is generally the best one, right? In most cases, you're going to do that, and you're going to get a bunch of similarity scores, right? You're going to see the score of how similar each document or each item in your data set is against the search query that I give you. And based on those similarity scores, you're going to see how well those items match with my search query, and then you're going to rank them, right?
And then you're going to display, let's say, the top 10 or the top 20 search results. You're going to sort them by the similarity scores that you generate from the cosine similarity over here, and then you're going to just rank them by that score and display the top 10 or 20 results to me, right? And that is how you implement semantic search, right?
So that's a very high-level architectural overview of how this works, right? The entire process and the algorithm you follow. In the next video, I'm going to actually implement this in code. I'm going to build a very simple implementation of semantic search. We're going to be able to search data through simple text, right? We won't need to match the keywords. We'll just need to match the intent or the meaning behind the words, right?
So we're going to do that in the next video or in some future video. But for now, I just wanted to teach you how semantic search works under the hood. So when you search for something on Google, and even though the keywords don't match, Google still gives you some pretty decent results, this is how it does that.
And also, when you talk to ChatGPT and ChatGPT is able to understand what you're trying to say, even though you don't match the specific keywords, this is how it's doing that. It's using vectors. It's using embeddings, right? It's using semantic search to tell what exactly you mean, even if you don't say the exact right words, right?
This is how AI and chat models and search is working under the hood. So I hope you're enjoying the work I'm doing over here in the videos I'm making. If you are, thank you, and leave a like, please, and subscribe.
This is a very fascinating topic that even I just recently learned like a month or two ago, and it's just amazing how beautiful technology can be when you actually understand it. So yeah, if you enjoyed this video and if you want to see more content like this, please leave a like, subscribe, share the video, comment down below what you think about the video. If you have any questions or something, I'll make sure to answer them. And yeah, thank you for watching.
Lastly, quick self-promotion. This is my web agency's website, and I build web apps and mobile apps and other software for people and businesses. If that is something you're interested in, or if you know somebody who's interested in that, guys, top link in the description is going to take you to book a call with me, which is completely free. We can talk about your project, we can discuss it, and we can get started working on it.
This is what I do for a living when I'm not recording videos, right? I build stuff for other people. So if you want to hire me to do that for you as well, then top link in the description, book a call, completely free. Let's get started.
Other than that, thank you for watching the video, and I will see you in the next one.
Share this article
Link copied!
Share it on Instagram.
Dude, you’re at the bottom of my landing page.
Just book a call already if you’re that interested.