IndiaIndian Nationals
1800 210 2020
ForiegnForeign Nationals
+918068792934
logologo
Home
About
Director's Message
Blogs
HomeAbout
Director's MessageBlogs
Limited Seats Available

RAG Architecture Explained: Components, Workflow, Types & Python Implementation

  1. Home
  2. Blog
  3. RAG Architecture Explained: Components, Workflow, Types & Python Implementation

By Rahul Singh

Updated on Oct 16, 2026

Share:

Quick Overview:

  • RAG architecture connects external knowledge sources with an LLM to generate the response using the collected information.

  • It includes three different phases which are data preparation and indexing, query processing, retrieval and generation, and evaluation and monitoring.

  • Common RAG architecture types include Naive RAG, Hybrid RAG, Graph RAG, Agentic RAG, Self-RAG, Corrective RAG, Adaptive RAG, and Multimodal RAG.

  • In this blog you will explore what is RAG architecture in AI, along with its types and making a RAG pipeline using Python.

Understanding RAG architecture is an important step towards evaluating how AI systems can support business goals. The Executive Programme in Technology & AI Leadership helps professionals strengthen their technology leadership perspective and make informed decisions about AI adoption and implementation.

RAG Architecture: Overview

The RAG architecture shows that how data sources, embedding models, retrieval systems, LLMs and vector databases work along to answer the questions using the relevant information.

For example, A company want to build an AI assistant that answer questions of the employees about the company HR policies. It may contain 1 employee handbook, 5 different leave policies, 3 benefit documents, and other internal records.

The RAG system processes all these documents, converts them into numerical representations and store them in a database. Whenever any employee asks,  "How many paid leaves can I take in a year?" The system retrieves the most relevant policy details. Then the LLM uses this information to generate the final answer.

A RAG system has commonly these three main stages:

  1. Data ingestion and indexing: It collects the document, prepare it, creates the embedding and store it in a database.

  2. Query processing and retrieval: Then it processes the user’s question and retrieves the relevant information from the data available in the database.

  3. LLM response generation: A LLM then combines the question with the collected context and provides a response.

High-Level RAG Architecture Diagram

Now let’s understand the ingestion and query processing by the help of RAG architecture diagram:

RAG architecture diagram showing data ingestion, document extraction, chunking, embedding generation, vector database storage, query processing, relevant context retrieval, and LLM-generated responses.RAG architecture diagram showing data ingestion, document extraction, chunking, embedding generation, vector database storage, query processing, relevant context retrieval, and LLM-generated responses.

Now let’s explore the core components of RAG architecture in detail to understand the topic more clearly.

Core Components and Phases of RAG Architecture

The RAG Architecture consists of mainly three phases and components such as Data Source, Embedding models, Reranking model, etc. Let’s explore each phase and component, what specific role each phase and component has.

Phase 1: Data Preparation and Indexing

1. Data Sources

Data sources provide the information that a RAG system uses to answer questions. Data sources are the information that a RAG system uses to answer questions. Common sources includes PDF files, documents, websites, different databases, articles etc.

In the example discussed above the HR assistant can use 4 types of sources such as employee handbooks, leave policies, benefits documents, and company guidelines.

2. Document Processor

The document processor is used to extract and prepare the information which is collected from different sources, so the system can read and search it. 

It is also used to handle the formatting issues, repetitive content and missing text.

For example, it can extract text from PDFs, removing unnecessary things from the websites and more.

3. Chunking Strategy

In chunking, it divides a long document into smaller sections by which the system can search specific information.

For example, in HR assistant model a 50 page employee handbook can be divided into smaller sections which covers the leave policies, payroll, workplace conduct, and employee benefits.

4. Embedding Model

An embedding model is used to convert each text chunk into a numerical vector that shows its meaning. The question asked by the user is also converts into a vector so the system can search for the related content only.

For example, If any employee asks, "How many paid leaves do I get?" and "What is my annual leave allowance?" Both are same thing but the wording are different. So the embedding model help the system to identify this relationship.

5. Vector Database and Index

A vector database is used to store the embeddings and some related information like text, document IDs and metadata. 

The indexes in the vector database helps the system to search in large collections without comparing each stored vectors individually.

Some common technologies are FAISS, Pinecone, Qdrant, Milvus, and Weaviate. FAISS is similarity search technology, whereas the rest provides vector databases or search functionality.

Also Read: What Is Semantic Search? How It Works, Benefits & Examples

Phase 2: Query Processing, Retrieval, and Generation

1. Retriever

Retriever's function is to retrieve the relevant data from the indexed data set. It can involve vector similarity search, keyword search, metadata filtering, or any combination of these techniques.

For instance, if an employee queries about the annual leave, then the retriever will fetch the relevant data regarding leave policies from the HR documents stored.

2. Reranking Model

Once the retrieval process provides the response, then there may be 10 types of information, which is not necessarily the case as all the 10 types of information are equally relevant. 

So, the reranking model comes to test the query against all the collected information and ranks the most relevant at the top.

3. Large Language Model (LLM)

The role of LLM is to provide the response by using the information collected and the user’s query in natural language.

For example, an employee asks, "How many paid leaves can I take in a year?" The LLM uses the relevant HR policy passage to explain the company's annual leave allowance.

The RAG system also able to tell the LLM to say when the available documents do not contain enough information, which help to reduce unsupported answers, but it does not guarantee that every response will be correct.

Phase 3: Evaluation and Monitoring

Evaluation and monitoring helps the developers check whether the RAG system works as expected or not.

They can track metrics such as:

  • Retrieval quality

  • Answer accuracy

  • Response time

  • Cost

  • Failure rate

Types of RAG Architecture

There are different types of RAG architecture such as Naive RAG, Agentic RAG, Corrective RAG (CRAG), and more which can be designed in different ways depending on the complexity of the task and the retrieval requirements. 

Some common types of RAG Architecture are:

RAG Architecture

How It Works

Best Suited For

Naive RAG

Retrieves relevant text chunks and sends them to an LLM to generate an answer.

Basic question-answering systems

Hybrid RAG

Combines keyword search with vector search to find relevant information.

Enterprise search and document retrieval

Graph RAG

Uses a knowledge graph to connect entities and relationships across documents.

Complex questions involving multiple relationships

Agentic RAG

Uses AI agents to plan searches, call tools, and retrieve information in multiple steps.

Complex, multi-step tasks

Self-RAG

Checks the need for retrieval and evaluates the relevance and support of generated answers.

Tasks that need better answer reliability

Corrective RAG (CRAG)

Checks retrieved documents and triggers other search methods when results are weak.

Questions where initial search results may be insufficient

Adaptive RAG

Chooses a retrieval approach based on the complexity of the question.

Systems handling simple and complex queries

HyDE

Generates a hypothetical answer to help find relevant documents through vector search.

Queries that are difficult to match directly

Multimodal RAG

Retrieves information from text, images, audio, video, and other formats.

Applications using different types of data

Modular RAG

Uses separate modules for retrieval, routing, memory, and answer generation.

Systems that need flexible components


Now let’s look at how you can build a RAG architecture in Python using OpenAI and FAISS.

Also Read: Supervised vs Unsupervised Learning: Differences, Examples, and Applications

Building a RAG Architecture in Python

You can build a basic Retrieval-Augmented Generation (RAG) system in Python using OpenAI embeddings, FAISS, and an LLM.

In this example, you will build an HR assistant that answers employee questions using company policy documents.

The system follows these 5 steps:

Step 1: Install the Required Libraries

Run this command in Google Colab or a Python notebook.

!pip install -q openai faiss-cpu numpy

You will use:

Library

Purpose

openai

Creates embeddings and generates answers.

faiss-cpu

Searches for relevant text chunks using vector similarity.

numpy

Stores and normalizes numerical vectors.

You also need an OpenAI API key. The code below asks for the key without displaying it on screen.

Step 2: Import Libraries and Set Up the API Key

import os

import getpass

import numpy as np

import faiss


from openai import OpenAI


# Enter your API key securely

if not os.getenv("OPENAI_API_KEY"):

    os.environ["OPENAI_API_KEY"] = getpass.getpass(

        "Enter your OpenAI API key: "

    )


# Create the API client

client = OpenAI()


print("RAG environment is ready.")

Expected output:

Enter your OpenAI API key: [hidden]

RAG environment is ready.

Step 3: Create Sample HR Documents

In this example, the RAG system can use 5 sample documents which cover annual leave, sick leave, etc.

documents = [

    {

        "title": "Annual Leave Policy",

        "text": (

            "Full-time employees receive 20 paid annual leave days "

            "per calendar year. Employees should submit annual leave "

            "requests through the HR portal at least 5 working days "

            "before the planned leave. A manager must approve each "

            "request before the employee takes leave. Unused annual "

            "leave can carry over up to 5 days into the next calendar "

            "year. Part-time employees receive leave on a prorated "

            "basis according to their contract."

        )

    },

    {

        "title": "Sick Leave Policy",

        "text": (

            "Employees receive 10 paid sick leave days per calendar "

            "year. If an employee is absent for more than 2 consecutive "

            "working days, the employee may be asked to provide a "

            "medical certificate. Employees should inform their "

            "manager as soon as possible when taking sick leave."

        )

    },

    {

        "title": "Parental Leave Policy",

        "text": (

            "Eligible primary caregivers can take 16 weeks of paid "

            "parental leave after the birth or adoption of a child. "

            "Eligible secondary caregivers can take 4 weeks of paid "

            "parental leave. Employees should submit documents to HR "

            "at least 30 days before planned leave when possible."

        )

    },

    {

        "title": "Health Benefits Policy",

        "text": (

            "Full-time employees can enroll in the company health "

            "insurance plan after 30 days of employment. The plan "

            "includes medical, dental, and vision coverage. Employees "

            "can add eligible dependents during the enrollment period."

        )

    },

    {

        "title": "Working Hours Policy",

        "text": (

            "Standard working hours are 9:30 AM to 6:00 PM, Monday "

            "through Friday, with a 1-hour lunch break. Employees "

            "should record attendance in the HR portal. Flexible "

            "schedules require manager approval."

        )

    }

]


print("Number of documents:", len(documents))


Expected output:

Number of documents: 5

Step 4: Split the Documents into Smaller Chunks

This step create chunks of up to 55 words, with an overlap of 10 words between consecutive chunks.

def split_text(text, chunk_size=55, overlap=10):

    words = text.split()

    chunks = []

    start = 0


    while start < len(words):

        end = min(start + chunk_size, len(words))

        chunks.append(" ".join(words[start:end]))


        if end == len(words):

            break


        start = end - overlap


    return chunks



# Split all documents and retain their titles

chunks = []


for document in documents:

    text_chunks = split_text(document["text"])


    for chunk_number, text_chunk in enumerate(text_chunks, start=1):

        chunks.append({

            "title": document["title"],

            "chunk_id": chunk_number,

            "text": text_chunk

        })


print("Total text chunks:", len(chunks))

print("\nFirst text chunk:")

print(chunks[0]["text"])

Expected output:

The first chunk will contain text from the Annual Leave Policy.

Step 5: Generate Embeddings

Here, text-embedding-3-small creates the embeddings.

def create_embeddings(texts, batch_size=64):

    vectors = []


    for start in range(0, len(texts), batch_size):

        batch = texts[start:start + batch_size]


        result = client.embeddings.create(

            model="text-embedding-3-small",

            input=batch

        )


        # Keep embeddings in the same order as the input texts

        batch_vectors = sorted(

            result.data,

            key=lambda item: item.index

        )


        vectors.extend(

            item.embedding for item in batch_vectors

        )


    return np.array(vectors, dtype="float32")



# Create embeddings for all document chunks

chunk_texts = [chunk["text"] for chunk in chunks]

chunk_vectors = create_embeddings(chunk_texts)


print("Number of embeddings:", len(chunk_vectors))

print("Embedding dimensions:", chunk_vectors.shape[1])

Expected output:

Number of embeddings: [depends on the number of chunks]

Embedding dimensions: 1536

Step 6: Store Embeddings in a FAISS Index

The code normalizes the vectors and uses inner-product search to rank results by cosine similarity.

# Normalize vectors for cosine similarity search

faiss.normalize_L2(chunk_vectors)


# Create the vector search index

embedding_dimension = chunk_vectors.shape[1]

index = faiss.IndexFlatIP(embedding_dimension)


# Add the embeddings to the index

index.add(chunk_vectors)


print("FAISS index created successfully.")

print("Vectors stored:", index.ntotal)

Expected output:

FAISS index created successfully.

Vectors stored: [same as the number of chunks]

FAISS supports vector similarity search. This example uses an in-memory index, so the index is not retained when the runtime is reset.

Step 7: Retrieve Relevant Information

When an employee asks a question, the system converts it into an embedding and searches the FAISS index for the 3 most relevant chunks.

question = "How many paid annual leave days can a full-time employee take each year?"


# Convert the question into an embedding

question_vector = create_embeddings([question])


# Normalize the query vector

faiss.normalize_L2(question_vector)


# Retrieve the 3 most relevant chunks

top_k = min(3, len(chunks))


scores, indices = index.search(

    question_vector,

    top_k

)


retrieved_chunks = []


for score, chunk_index in zip(scores[0], indices[0]):

    if chunk_index >= 0:

        chunk = chunks[chunk_index]


        retrieved_chunks.append({

            "title": chunk["title"],

            "text": chunk["text"],

            "score": float(score)

        })


print("Question:", question)

print("\nRetrieved sources:")


for item in retrieved_chunks:

    print("-", item["title"])

Example output:

Question: How many paid annual leave days can a full-time employee take each year?

Retrieved sources:

- Annual Leave Policy

- Annual Leave Policy

- Sick Leave Policy

Step 8: Generate an Answer Using an LLM

The final step sends the question and retrieved passages to an LLM. The prompt tells the model to use the supplied documents and state when they do not contain the answer.

# Combine the retrieved chunks into context

context = "\n\n".join(

    f"[Source: {item['title']}]\n{item['text']}"

    for item in retrieved_chunks

)


# Generate a grounded answer

response = client.responses.create(

    model="gpt-4.1-mini",

    instructions=(

        "You are an HR assistant. Answer the user's question "

        "using only the supplied context. Keep the answer simple "

        "and concise. Cite the source title in square brackets. "

        "If the context does not contain the answer, say: "

        "'I couldn't find that information in the available documents.'"

    ),

    input=f"""

    Question:

    {question}


    Retrieved context:

    {context}

    """,

    store=False

)


print("Question:", question)

print("\nGenerated Answer:")

print(response.output_text)

Example output:

Question: How many paid annual leave days can a full-time employee take each year?


Generated Answer:

Full-time employees receive 20 paid annual leave days per calendar year.

You must submit your leave request through the HR portal at least

5 working days in advance and get approval from your manager.

[Annual Leave Policy]

The exact wording may vary because the LLM generates the response. The answer should still reflect the retrieved policy when the relevant passages are available.

Also Read: Decision Tree Algorithm in Machine Learning: How It Works, Types, and Examples

Conclusion

Now, it is easy for you to understand how RAG architecture combines data ingestion, embeddings, indexing, retrieval and LLM generation in a single workflow. It has two central pipelines which prepares the information for search and use the collected context to answer the user's questions.

Designing the right RAG design pattern depends on the data, complexity of query, and the expected answer quality. You can start with the Basic RAG and later move on to Graph RAG and agentic RAG for more complex tasks.

Rahul Singh

Rahul Singh

24+ of articles published


Current role in the industry :

Associate - Content Marketing

Education Qualification :

B.Tech in Computer Science & Engineering

Expertise :

Artificial intelligenceMachine Learning (ML)Data ScienceFull-Stack DevelopmentData Structures & Algorithms

Tools & Technologies :

PythonReact.js & Next.jsJavaScript (ES6+)SQLTailwind CSSNode.js & MongoDBGit & GitHubSEO Tools (SEMRush)Google Search ConsoleTableau / Power BIFigma

About

Rahul Singh is an Associate Content Writer, with a strong interest in Generative AI, Agentic AI and AI-Native Software Engineering. He combines technical development skills with data-driven strategies to build scalable applications and optimize digital content. Rahul specializes in simplifying complex concepts across AI, ML and software development into practical, easy-to-understand insights, helping learners understand how AI products, systems and services are built and applied. He focuses on real world applications and explains advanced topics in a clear, step by step manner so you can follow along without confusion. His work connects theory with hands-on examples, covering AI-assisted development, intelligent automation and AI integration in software applications. He aims to help you learn faster, create better projects, and apply your knowledge confidently in real scenarios.

Follow me on :

No blogs published yet.

Frequently Asked Questions

General

Ready to Take the Next Step? Enroll Today!

Ready to Take the Next Step? Enroll Today!