Skip to main content

1. Import FAISS

FAISS is used to perform efficient similarity search. It stores the document embeddings in a vector index and helps find the documents most similar to the user’s query. Later, you use:
to create the index and:
to retrieve similar documents.

2. Import the Gemini SDK

This imports the Google GenAI library. use it to connect your Python application to the Gemini API. Later:
creates a Gemini client. And:
sends prompt to the Gemini model.

3. Import SentenceTransformer

SentenceTransformer converts text into numerical vectors called embeddings. For example:
These vectors represent the semantic meaning of the text.

Step 1: Load the Embedding Model

This loads the model:
The model converts sentences into embedding vectors. For this model, each embedding typically has:
The same embedding model is used for both:
This is important because the query and documents need to exist in the same vector space for meaningful similarity comparison.

Step 2: Create Sample Documents

This list acts as your small knowledge base. You have six documents:
In a real RAG application, these documents could come from:
  • PDFs
  • Websites
  • Databases
  • Company documents
  • Text files
  • Documentation

Step 3: Convert Documents into Embeddings

The encode() function converts all six documents into numerical vectors. Before:
After:
The approximate shape is:
This means:

Why normalize_embeddings=True?

Normalizes each embedding vector to have a length of 1. This is useful because FAISS index uses:
After normalization:
Therefore:

Step 4: Get the Embedding Dimension

Suppose:
returns:
Then:
is:
The number of documents. And:
is:
The number of values in each embedding. Therefore:
FAISS needs this value when creating the vector index.

Step 5: Create a FAISS Index

This creates a FAISS index. Let’s break it down:

IndexFlat

Performs an exact similarity search. It compares the query against all stored vectors.

IP

Means:
Since we normalized the embeddings, inner product behaves like cosine similarity. So:
The index expects vectors with:

Step 6: Add Document Embeddings

This adds all six document vectors to the FAISS index. Conceptually:
The vector positions correspond to the original positions in the documents list.
index.ntotal returns the total number of vectors inside the index. Output:

Step 7: Get the User’s Query

This waits for the user to enter a question. For example:
The value is stored in:
So:

Step 8: Convert the Query into an Embedding

FAISS cannot directly understand text. Therefore:
must be converted into:
The query embedding shape is approximately:
Meaning:
The query is placed inside a list:
because the embedding model and FAISS search work with batches of vectors. You again use:
so the query vector is normalized in the same way as the document vectors.

Step 9: Retrieve the Top-K Documents

This means want the three most relevant documents. Then:
FAISS compares the query embedding with all stored document embeddings. The process is:
FAISS returns two things:
and:

Understanding scores

Suppose:
contains:
The scores represent similarity. Because we use normalized embeddings with IndexFlatIP:
Higher is better.

Understanding indices

Suppose:
contains:
These are positions in the original documents list. Therefore:
is the first result.
is the second result.
is the third result.

Step 10: Get the Retrieved Documents

First:
creates an empty list. will store the top three retrieved documents inside it.

Loop Through the Results

Suppose:
is:
Then the loop runs like this:

Retrieve the Original Document

If:
then:
which gives:

Get the Similarity Score

If:
then:
This retrieves the similarity score for the first result.

Store the Document

The retrieved document is added to the list. After three iterations:

rank starts from 0, but humans normally start counting from 1. Therefore:

Example:

The:
formats the score to four decimal places. For example:
becomes:

Step 11: Combine Documents into Context

The retrieved documents are currently stored as a list:
The join() method combines them into one string. The:
adds two line breaks between documents. The final context might look like:
This context will be given to Gemini.

Step 12: Create the RAG Prompt

The f before the string:
means this is an f-string. It allows Python variables to be inserted directly. These variables:
and:
are replaced with their actual values. For example:
This is the augmentation step of RAG. The retrieved information is added to the prompt before sending it to the LLM.

Step 13: Create the Gemini Client

This creates a client that communicates with the Gemini API. The client uses Gemini API key, typically stored as an environment variable:
program can then send prompts to a Gemini model. Conceptually:

Step 14: Send the Prompt to Gemini

This sends complete RAG prompt to the Gemini model. The prompt contains:
The model then reads the context and generates an answer. The response is stored in:

Step 15: Print the Final Answer

This prints a heading:
Then:
prints the text generated by Gemini. For example:

Complete Flow

Stage 1: Indexing

This happens before the user asks the question.
In code:

Stage 2: Retrieval and Generation

After the user enters a question:

How This Relates to RAG

The three main parts are:

1. Retrieval

FAISS retrieves relevant documents.

2. Augmentation

and:
The retrieved documents are added to the LLM prompt.

3. Generation

Gemini generates the final natural-language answer.

Final Architecture

The most important concept is:
So complete project is a basic implementation of: