# vinayak258/ncert-doubt-solver architecture

> Architecture diagram of the GitHub repository vinayak258/ncert-doubt-solver, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-20). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/vinayak258/ncert-doubt-solver
- Repository: https://github.com/vinayak258/ncert-doubt-solver

## Overview

1. **What this repo is**
   - This is a split **RAG system for NCERT textbook Q&A** with three main runtime concerns: document ingestion/indexing, answer generation, and a student-facing UI.
   - The architecture is intentionally **service-oriented**: frontend, backend RAG service, and offline data-prep pipelines are separated.

2. **Primary request path**
   - A user asks a question in the **Next.js frontend**.
   - The frontend sends the query over HTTP to the **FastAPI backend**.
   - The backend retrieves relevant textbook chunks from **FAISS** and then calls **Google Gemini** to generate the final answer grounded in that retrieved context.

3. **Frontend boundary**
   - The production UI lives in `frontend/` and uses **Next.js 14 App Router**, React, and Tailwind.
   - Its job is presentation and API orchestration only; it does not contain retrieval or generation logic.
   - The local Python `ui/` directory appears to be an auxiliary UI entry point, but the main documented user-facing app is the Next.js frontend.

4. **Backend API boundary**
   - The API layer is in `api/` with `main.py`, `routes/query.py`, and `schemas.py`.
   - This layer defines request/response contracts and exposes the query endpoint(s) consumed by the frontend.
   - It acts as the HTTP boundary around the RAG pipeline rather than embedding business logic itself.

5. **RAG core**
   - The reusable RAG implementation is in `rag/`: `pipeline.py`, `generator.py`, and `llm_config.py`.
   - This is where retrieval results are turned into prompts and passed to the LLM.
   - The prompt templates live under `prompts/`, which means prompt formatting is treated as a first-class, versioned part of the architecture.

6. **Retrieval subsystem**
   - Semantic search uses **Sentence-Transformers embeddings** and **FAISS** vector storage.
   - The vector index and metadata are persisted as local artifacts, not in an external database.
   - `vector_store/` contains the index/retriever abstraction used by the RAG pipeline.

7. **Ingestion and indexing pipeline**
   - The offline pipeline is in `ingestion/`, with PDF-to-text conversion, OCR, cleaning, and chunking.
   - `embeddings/` builds embeddings and constructs the FAISS index from the cleaned chunks.
   - This is a build-time data pipeline: **raw PDFs → cleaned text/chunks → embeddings → FAISS index + metadata**.

8. **Data artifacts and persistence**
   - The canonical input corpus is stored under `rag_service/data/raw_books/` as NCERT PDFs.
   - Preprocessed chunks are stored in `rag_service/data/cleaned_text/chunks.json`.
   - The retrieval store is persisted in `rag_service/data/vector_store/faiss.index` and `metadata.pkl`.
   - There is no separate relational or document database in the architecture.

9. **Standalone deployable backend package**
   - `rag_service/` is a self-contained deployable version of the backend, with its own `app.py`, `requirements.txt`, `Dockerfile`, and an internal `src/` tree mirroring the root-level RAG modules.
   - This is an important packaging boundary: the repo keeps shared logic at the root, but the production/deployment image uses the `rag_service` layout.
   - The README’s hosted backend and Render deployment refer to this packaged service.

10. **Operational flow and tooling**
   - `scripts/run_ingestion.py`, `scripts/run_rag.py`, and `scripts/run_retrieval.py` orchestrate offline ingestion, manual RAG runs, and retrieval evaluation.
   - `evaluation/retrieval_test.py` is for checking retrieval quality rather than end-user serving.
   - Docker Compose supports local multi-service startup, while `k8s/` contains Kubernetes manifests for the same service split.
   - GitHub Actions CI is present in `.github/workflows/ci.yml`, and deployment metadata exists in `render.yaml`.

11. **External dependencies that shape the architecture**
   - The main external service is **Google Gemini**, used only at generation time.
   - The backend is tuned for constrained memory, so model loading is described as **lazy-loaded** and the embedding model is intentionally lightweight.
   - This explains why the system prefers local artifacts plus on-demand inference rather than heavier always-on infrastructure.

12. **How to draw the architecture**
   - Put the **Next.js frontend** at the edge.
   - Behind it, place a **FastAPI query service** wrapping the **RAG pipeline**.
   - Connect that pipeline to two internal data subsystems: the **FAISS vector store** for retrieval and **Gemini** for generation.
   - Add a separate offline lane from **NCERT PDFs → ingestion/cleaning/chunking → embeddings/index build → persisted FAISS artifacts**.
   - Show `rag_service/` as the production packaging of the backend and data artifacts, not as a separate business capability.

Main entry points: [`rag/pipeline.py`](https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag/pipeline.py) (RAG pipeline), [`api/routes/query.py`](https://github.com/vinayak258/ncert-doubt-solver/blob/main/api/routes/query.py) (Query route), [`rag/generator.py`](https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag/generator.py) (Generator), [`ingestion/text_cleaner.py`](https://github.com/vinayak258/ncert-doubt-solver/blob/main/ingestion/text_cleaner.py) (Clean chunks)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Frontend"]
  node_frontend_app["Next.js app<br/>Next.js UI"]
  node_frontend_layout["UI shell<br/>React layout<br/>[layout.tsx]"]
  node_frontend_page["Chat page<br/>React page<br/>[page.tsx]"]
end

subgraph group_backend["Backend"]
  node_api_main["API app<br/>FastAPI entry<br/>[main.py]"]
  node_api_query["Query route<br/>HTTP route<br/>[query.py]"]
  node_api_schemas["Contracts<br/>Pydantic schemas<br/>[schemas.py]"]
  node_rag_pipeline["RAG pipeline<br/>orchestrator<br/>[pipeline.py]"]
  node_rag_generator["Generator<br/>LLM assembly<br/>[generator.py]"]
  node_llm_config["LLM config<br/>model config<br/>[llm_config.py]"]
  node_vector_retriever["Retriever<br/>[retriever.py]"]
  node_prompt_templates["Prompts<br/>prompt assets"]
end

subgraph group_offline["Offline pipeline"]
  node_ingestion_pdf["PDF extract<br/>ingestion<br/>[pdf_to_text.py]"]
  node_ingestion_clean["Clean chunks<br/>text cleanup<br/>[text_cleaner.py]"]
  node_embed_build["Index build<br/>embedding build<br/>[build_index.py]"]
end

subgraph group_packaging["Packaging"]
  node_vector_index[("FAISS store<br/>vector index<br/>[faiss.index]")]
  node_raw_books["NCERT PDFs<br/>source corpus"]
  node_cleaned_chunks["Chunk corpus<br/>processed data<br/>[chunks.json]"]
  node_rag_service_pkg["Backend bundle<br/>deployable package"]
end

subgraph group_ops["Operations"]
  node_scripts_ops["Run scripts<br/>tooling<br/>[run_rag.py]"]
  node_deploy_ops["Deploy config<br/>deployment<br/>[docker-compose.yml]"]
end

node_frontend_page -->|"HTTP query"| node_api_query
node_frontend_layout -.->|"composes"| node_frontend_app
node_api_main -->|"mounts"| node_api_query
node_api_query -.->|"validates"| node_api_schemas
node_api_query -->|"invokes"| node_rag_pipeline
node_rag_pipeline -->|"retrieves"| node_vector_retriever
node_rag_pipeline -->|"generates"| node_rag_generator
node_rag_generator -.->|"loads"| node_llm_config
node_rag_generator -.->|"formats"| node_prompt_templates
node_vector_retriever -->|"reads"| node_vector_index
node_ingestion_pdf -->|"feeds"| node_ingestion_clean
node_ingestion_clean -->|"writes"| node_cleaned_chunks
node_cleaned_chunks -->|"input"| node_embed_build
node_raw_books -->|"source"| node_ingestion_pdf
node_embed_build -->|"builds"| node_vector_index
node_rag_service_pkg -.->|"packages"| node_rag_pipeline
node_rag_service_pkg -.->|"ships"| node_vector_index
node_scripts_ops -.->|"runs"| node_ingestion_clean
node_scripts_ops -.->|"tests"| node_rag_pipeline
node_deploy_ops -.->|"deploys"| node_api_main
node_deploy_ops -.->|"deploys"| node_frontend_app

click node_frontend_app "https://github.com/vinayak258/ncert-doubt-solver/tree/main/frontend/src/app"
click node_frontend_layout "https://github.com/vinayak258/ncert-doubt-solver/blob/main/frontend/src/app/layout.tsx"
click node_frontend_page "https://github.com/vinayak258/ncert-doubt-solver/blob/main/frontend/src/app/page.tsx"
click node_api_main "https://github.com/vinayak258/ncert-doubt-solver/blob/main/api/main.py"
click node_api_query "https://github.com/vinayak258/ncert-doubt-solver/blob/main/api/routes/query.py"
click node_api_schemas "https://github.com/vinayak258/ncert-doubt-solver/blob/main/api/schemas.py"
click node_rag_pipeline "https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag/pipeline.py"
click node_rag_generator "https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag/generator.py"
click node_llm_config "https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag/llm_config.py"
click node_vector_retriever "https://github.com/vinayak258/ncert-doubt-solver/blob/main/vector_store/retriever.py"
click node_vector_index "https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag_service/data/vector_store/faiss.index"
click node_prompt_templates "https://github.com/vinayak258/ncert-doubt-solver/blob/main/prompts/rag_query_template.txt"
click node_ingestion_pdf "https://github.com/vinayak258/ncert-doubt-solver/blob/main/ingestion/pdf_to_text.py"
click node_ingestion_clean "https://github.com/vinayak258/ncert-doubt-solver/blob/main/ingestion/text_cleaner.py"
click node_embed_build "https://github.com/vinayak258/ncert-doubt-solver/blob/main/embeddings/build_index.py"
click node_raw_books "https://github.com/vinayak258/ncert-doubt-solver/tree/main/rag_service/data/raw_books"
click node_cleaned_chunks "https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag_service/data/cleaned_text/chunks.json"
click node_rag_service_pkg "https://github.com/vinayak258/ncert-doubt-solver/tree/main/rag_service"
click node_scripts_ops "https://github.com/vinayak258/ncert-doubt-solver/blob/main/scripts/run_rag.py"
click node_deploy_ops "https://github.com/vinayak258/ncert-doubt-solver/blob/main/docker-compose.yml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_frontend_app,node_frontend_layout,node_frontend_page toneBlue
class node_api_main,node_api_query,node_api_schemas,node_rag_pipeline,node_rag_generator,node_llm_config,node_vector_retriever,node_prompt_templates toneAmber
class node_ingestion_pdf,node_ingestion_clean,node_embed_build toneMint
class node_vector_index,node_raw_books,node_cleaned_chunks,node_rag_service_pkg toneRose
class node_scripts_ops,node_deploy_ops toneIndigo
```

## Components

### Frontend

Student-facing Next.js UI layer.

- [Next.js app](https://github.com/vinayak258/ncert-doubt-solver/tree/main/frontend/src/app): Next.js UI · Production student-facing interface for asking questions and showing answers. · `frontend/src/app`
- [UI shell](https://github.com/vinayak258/ncert-doubt-solver/blob/main/frontend/src/app/layout.tsx): React layout · App Router shell and shared presentation structure. · `frontend/src/app/layout.tsx`
- [Chat page](https://github.com/vinayak258/ncert-doubt-solver/blob/main/frontend/src/app/page.tsx): React page · Main interactive page that drives question submission. · `frontend/src/app/page.tsx`

### Backend

HTTP API and RAG serving layer.

- [API app](https://github.com/vinayak258/ncert-doubt-solver/blob/main/api/main.py): FastAPI entry · Backend application entrypoint for serving the query API. · `api/main.py`
- [Query route](https://github.com/vinayak258/ncert-doubt-solver/blob/main/api/routes/query.py): HTTP route · Endpoint handling question requests from the frontend. · `api/routes/query.py`
- [Contracts](https://github.com/vinayak258/ncert-doubt-solver/blob/main/api/schemas.py): Pydantic schemas · Request and response shapes for the API boundary. · `api/schemas.py`
- [RAG pipeline](https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag/pipeline.py): orchestrator · Coordinates retrieval, prompt assembly, and answer generation. · `rag/pipeline.py`
- [Generator](https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag/generator.py): LLM assembly · Builds prompts and turns retrieved context into final answers. · `rag/generator.py`
- [LLM config](https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag/llm_config.py): model config · Google Gemini and runtime settings for answer generation. · `rag/llm_config.py`
- [Retriever](https://github.com/vinayak258/ncert-doubt-solver/blob/main/vector_store/retriever.py): FAISS retriever · Semantic search over indexed textbook chunks. · `vector_store/retriever.py`
- [Prompts](https://github.com/vinayak258/ncert-doubt-solver/blob/main/prompts/rag_query_template.txt): prompt assets · System, user, and query templates used by the RAG pipeline. · `prompts/rag_query_template.txt`

### Offline pipeline

Ingestion, embedding, and retrieval build steps.

- [PDF extract](https://github.com/vinayak258/ncert-doubt-solver/blob/main/ingestion/pdf_to_text.py): ingestion · Converts NCERT PDFs into text and OCR output. · `ingestion/pdf_to_text.py`
- [Clean chunks](https://github.com/vinayak258/ncert-doubt-solver/blob/main/ingestion/text_cleaner.py): text cleanup · Normalizes and chunks extracted textbook text. · `ingestion/text_cleaner.py`
- [Index build](https://github.com/vinayak258/ncert-doubt-solver/blob/main/embeddings/build_index.py): embedding build · Creates embeddings and writes the FAISS artifacts. · `embeddings/build_index.py`

### Packaging

Deployable backend bundle and runtime artifacts.

- [FAISS store](https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag_service/data/vector_store/faiss.index): vector index · Local FAISS index and metadata used for retrieval. · `rag_service/data/vector_store/faiss.index`
- [NCERT PDFs](https://github.com/vinayak258/ncert-doubt-solver/tree/main/rag_service/data/raw_books): source corpus · Canonical textbook source material for the RAG system. · `rag_service/data/raw_books`
- [Chunk corpus](https://github.com/vinayak258/ncert-doubt-solver/blob/main/rag_service/data/cleaned_text/chunks.json): processed data · Persisted cleaned text chunks used to build and inspect the index. · `rag_service/data/cleaned_text/chunks.json`
- [Backend bundle](https://github.com/vinayak258/ncert-doubt-solver/tree/main/rag_service): deployable package · Standalone production packaging of the backend, RAG modules, and data artifacts. · `rag_service`

### Operations

Scripts and deployment automation.

- [Run scripts](https://github.com/vinayak258/ncert-doubt-solver/blob/main/scripts/run_rag.py): tooling · Orchestrates ingestion, manual RAG runs, and retrieval checks. · `scripts/run_rag.py`
- [Deploy config](https://github.com/vinayak258/ncert-doubt-solver/blob/main/docker-compose.yml): deployment · Docker Compose, Kubernetes, Render, and CI configuration for the split service setup. · `docker-compose.yml`

## Connections

- Chat page → Query route: HTTP query · User questions are sent from the frontend to the backend API.
- UI shell → Next.js app: composes · Shared UI shell supports the app routes.
- API app → Query route: mounts · FastAPI application exposes the query route.
- Query route → Contracts: validates · API payloads are checked against request and response schemas.
- Query route → RAG pipeline: invokes · Route hands the request to the RAG orchestrator.
- RAG pipeline → Retriever: retrieves · Pipeline fetches relevant textbook chunks for grounding.
- RAG pipeline → Generator: generates · Pipeline passes retrieved context into answer generation.
- Generator → LLM config: loads · Generator uses model configuration for Gemini inference.
- Generator → Prompts: formats · Prompt assets shape the final LLM prompt.
- Retriever → FAISS store: reads · Retriever queries the persisted FAISS artifacts.
- PDF extract → Clean chunks: feeds · Extracted text flows into cleaning and chunking.
- Clean chunks → Chunk corpus: writes · Processed chunks are persisted for index construction and inspection.
- Chunk corpus → Index build: input · Chunk corpus is embedded and indexed offline.
- NCERT PDFs → PDF extract: source · NCERT PDFs are the raw ingestion input.
- Index build → FAISS store: builds · Embedding pipeline produces the FAISS index and metadata.
- Backend bundle → RAG pipeline: packages · Deployable backend bundle contains the shared RAG code.
- Backend bundle → FAISS store: ships · Production package includes persisted retrieval artifacts.
- Run scripts → Clean chunks: runs · Scripts orchestrate offline preprocessing and indexing workflows.
- Run scripts → RAG pipeline: tests · Scripts support manual RAG execution and retrieval checks.
- Deploy config → API app: deploys · Operational configs deploy the backend service.
- Deploy config → Next.js app: deploys · Operational configs also deploy the frontend.
