1. Executive Summary & Architectural Decisions
Objective: Design a backend for generating NEET-aligned MCQs across Physics, Chemistry, Botany, and Zoology (180 Questions, 720 Marks).
Core Constraint: The system must be maintainable easily. Pure LLM generation (standard RAG with Vector DBs) is rejected due to the high risk of mathematical hallucinations and unpredictable structures.
Chosen Architecture: A Modular Monolith utilizing a Relational Database (PostgreSQL) to store a structured Knowledge Graph and Question Templates. Question generation relies on deterministic Python mathematical mutators paired with the Gemini API for linguistic formatting and distractor generation. Heavy ingestion tasks run on local GPUs, while Gemini handles final reasoning.
2. High-Level System Architecture
The system is divided into three major planes: Frontend, API & Orchestration, and the Data/AI Layer. Background tasks are handled via Celery to prevent API timeouts during complex generation processes.
3. Database Schema (Entity-Relationship Diagram)
By structuring data into Exams, Subjects, Topics, Concepts, and Templates, we completely bypass the need for fuzzy vector searches. We can deterministically query exactly what is needed for the exam blueprint.
4. Data Ingestion Pipeline
How raw, unstructured PDFs (from NEET data sources) are converted into structured templates and concepts using local hardware to save API costs.
5. Predictable Generation & Validation Agentic Flow
The core logic ensuring 0% hallucination. Math is done by deterministic Python code, while Gemini is restricted to formatting, distractor generation, and blind cross-validation.
6. API Layer & Contracts
RESTful interfaces for the Frontend application to communicate with the FastAPI backend.
Request Full Exam Generation
POST /api/v1/exams/generate -- Async Workflow
{
"exam_type": "NEET",
"difficulty_distribution": {
"easy": 0.60,
"medium": 0.30,
"hard": 0.10
},
"subjects": ["Physics", "Chemistry", "Botany", "Zoology"]
}
Returns a job_id to poll for status due to the ~2-3 minute generation time.
Fetch Generated Question
GET /api/v1/questions/{question_id} -- Sync Fetch
{
"id": "q-1234-abcd",
"subject": "Physics",
"topic": "Work, Energy and Power",
"difficulty": "Medium",
"stem_html": "A particle of mass m=2 kg is moving with velocity v=3 m/s. Calculate its kinetic energy.",
"options": [
{ "id": "A", "text_html": "9 J", "is_correct": true },
{ "id": "B", "text_html": "18 J", "is_correct": false },
{ "id": "C", "text_html": "6 J", "is_correct": false },
{ "id": "D", "text_html": "3 J", "is_correct": false }
],
"explanation_html": "Kinetic Energy K = (1/2)mv^2. Substituting values: K = (1/2)(2)(3^2) = 9 J."
}