Repository
NCERT-RAG
RAG assistant for NCERT textbooks — ChromaDB + MiniLM retrieval, Gemini answers, served with Django.
What it does
NCERT-RAG is a retrieval-augmented generation (RAG) assistant for NCERT textbooks, served through a small Django web app. You type a question ("Explain reflection of light"), it searches a local vector index of the textbook PDFs, and Gemini answers using only the retrieved passages. The page shows the answer alongside the source file and the similarity score of the best-matching chunk.
The repo ships with PDFs for:
| Class | Subjects |
|---|---|
| Class 10 | Maths, Science |
| Class 6 | English, Hindi |
Drop more PDFs into books/ and they are picked up on the next (re)index.
How it works
flowchart LR
A[books/**/*.pdf] -->|PyMuPDFLoader| B[Pages]
B -->|RecursiveCharacterTextSplitter<br/>1000 chars, 200 overlap| C[Chunks]
C -->|all-MiniLM-L6-v2| D[(ChromaDB<br/>cosine, persistent)]
Q[User question] -->|all-MiniLM-L6-v2| E[Query embedding]
E -->|top-k = 3| D
D --> F[Retrieved context]
F --> G[Gemini 2.5 Flash]
G --> H[Answer + source file + similarity]
- Ingest -
src/process_pdfs.pyloads every PDF under the books directory and tags each page with its source file. - Chunk - pages are split into ~1000-character chunks with 200 characters of overlap.
- Embed -
src/embeddings_manager.pyencodes chunks with the SentenceTransformerall-MiniLM-L6-v2. - Store -
src/Vector_store.pywrites them to a persistent ChromaDB collection (pdf_documents, cosine space). Indexing is skipped if the collection already has documents. - Retrieve -
src/RagRetriver.pyembeds the question and pulls the top 3 chunks. - Generate -
src/RAG.pystuffs the chunks into a prompt and callsgemini-2.5-flashvialangchain-google-genai.
Tech stack
- Web: Django 6 (single view + template), Waitress for serving
- Retrieval: LangChain (loaders, text splitters), ChromaDB, sentence-transformers
- Generation: Google Gemini 2.5 Flash through
langchain-google-genai - PDF parsing: PyMuPDF
Project structure
NCERT-RAG/
├── books/ # NCERT PDFs (class 10 maths/science, class 6 English/Hindi)
├── src/
│ ├── process_pdfs.py # load PDFs + split into chunks
│ ├── embeddings_manager.py
│ ├── Vector_store.py # ChromaDB wrapper
│ ├── RagRetriver.py # query -> top-k chunks
│ ├── RAG.py # prompt + Gemini call
│ └── rag_service.py # glues it all together (index + ask)
├── app/ # Django app: views.py, urls.py
├── rag/ # Django project settings
├── templates/index.html # question / answer UI
├── manage.py
├── serve.py # Waitress server on 127.0.0.1:8000
└── requirements.txt
Quickstart
git clone https://github.com/nabeelalikhan0/NCERT-RAG.git
cd NCERT-RAG
python -m venv .venv
# Windows: .venv\Scripts\activate macOS/Linux: source .venv/bin/activate
pip install -r requirements.txt
1. Add your Gemini API key. The code loads a .env file from the src/ folder:
# src/.env
GEMINI_API_KEY=your-key-here
2. Point the indexer at the books folder. app/views.py currently calls rag.index_directory(...) with an absolute Windows path. Change it to the books directory in your clone, for example:
rag.index_directory("books")
3. Run the server.
python manage.py runserver
# or, with Waitress:
python serve.py
Open http://127.0.0.1:8000 and ask a question. The first request downloads the embedding model and indexes all PDFs, so it takes a while; later requests reuse the persisted Chroma store.
Note: the vector store is persisted to
../data/vector_store, relative to the directory you launch the server from (i.e. adata/folder next to the repo). Delete that folder to force a full re-index.
Roadmap ideas
- Make the books path and vector-store path configurable via settings / env
- Build the
RAGServiceonce at startup instead of per request - Show all retrieved chunks (with page numbers) as citations, not just the top one