Skip to content
Devansh-SRPublic

About

AI tutoring that shows its sources. RAG-grounded doubt-solving, adaptive practice, and a live teacher dashboard — built for OOSC 4.0.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PATHSHALA

Grounded learning for equitable education access

OOSC 4.0 — Problem Statement 2: AI for Equitable Education Access

Python FastAPI React Vite ChromaDB Groq License


PATHSHALA is a grounded AI learning system built around one idea: a student's question deserves an answer that can be checked, not just believed. Every explanation PATHSHALA gives is retrieved from real textbook material and cited by source and page — the same standard you'd expect from a good tutor, not a chatbot guessing in the dark.

It ships three connected agents, not three disconnected demos:

Agent What it does
🔍 Grounded Doubt-Solving Agent Answers a student's question using retrieval-augmented generation over an indexed textbook corpus, with visible citations (source file + page + exact snippet) and a confidence score.
📝 Adaptive Practice Generator Generates MCQ practice questions from the same corpus, auto-targeting whichever topic the student is currently weakest in, at a difficulty that follows their live mastery score.
📊 Teacher-Facing Insight Agent Turns every doubt and every practice attempt into a class-wide topic heatmap and a ranked "needs attention" list — so a teacher can see who's struggling before the next test does.

They share one database, one mastery model, and one corpus — a student's practice history is what makes their next practice round adaptive, and what makes them show up on their teacher's dashboard. Nothing here is a disconnected point solution.

Quickstart • Why RAG • Architecture • Judging Criteria • Team


Why this is a RAG system, not "ChatGPT with a topic filter"

The distinction matters and it's checkable in under a minute:

  1. Ask PATHSHALA a question. The answer arrives with citations — the exact .txt file (or PDF + page number, once you load real textbook PDFs) the answer was pulled from, and a verbatim snippet.
  2. Embeddings run locally, via sentence-transformers — no API call, no cost, works offline. Only the final answer synthesis calls an LLM, and that call is instructed to answer strictly from the retrieved context, not from what it memorized during training.
  3. Ask something outside the corpus and PATHSHALA says so — it does not fabricate an answer to look useful. Try it: ask about a topic that isn't in backend/app/data/corpus/ and you'll get an honest "not found" rather than a hallucination.

This is what "citations to source" in the problem brief actually means in a shipped system, and it's the single easiest thing for a judge to verify live.


Architecture

React frontend (Vite, JS)
   │  HTTP requests, JWT in the Authorization header
   ▼
FastAPI backend
   │
   ├── Routers          auth · doubts · practice · insights · corpus
   │                        │
   │                        ▼
   └── Services          rag_service       → ChromaDB (local vector store,
                                              persisted to disk)
                          llm_service       → Groq (free tier) or Anthropic
                                              — one provider-agnostic adapter,
                                                generation only, not retrieval
                          mastery_service   → SQLite / Postgres
                                              (users, mastery, attempts, doubts)

(A boxed version of this same diagram is in the accompanying setup guide document, verified page-by-page against a rendered PDF export.)

Zero-cost by default. SQLite and ChromaDB are both local files — no managed database, no hosted vector DB subscription. The default LLM provider is Groq's free tier, so the entire stack — auth, retrieval, mastery tracking, the teacher dashboard, and generation — can run at zero cost. Anthropic is supported as a drop-in alternative; switch with one environment variable (LLM_PROVIDER) and nothing else in the codebase changes, since every LLM call is routed through a single provider-agnostic adapter in app/services/llm_service.py.

Data model

  • users — student or teacher, with role-gated access.
  • doubts — every question asked, its answer, and its citations (stored as JSON so the full provenance trail is queryable later).
  • practice_questions / attempts — generated questions and what the student answered, with correctness and timing.
  • topic_mastery — one row per (student, subject, topic), holding an exponential moving average of correctness. This is the join between "what a student got wrong" and "what the teacher dashboard shows" and "what gets asked next" — see backend/app/services/mastery_service.py for the exact update rule.

Why these technical choices

  • ChromaDB over a linear similarity scan — a real ANN vector index, the same category of tool used in production RAG systems, rather than a keyword-match demo dressed up as AI.
  • Local embeddings, API-only generation — retrieval keeps working even if the LLM API key or quota runs out; only the final synthesis step needs it. Keeps the zero-cost story honest.
  • Paragraph-aware chunking with overlap — avoids losing context at chunk boundaries (see _chunk_text in rag_service.py).
  • Strict JSON-contract prompting for question generation — the LLM is told to return only a JSON array; the parser defensively strips stray markdown fences and falls back to regex extraction if the model wraps its output in prose anyway.
  • EMA mastery over running accuracy — recent performance counts more than performance from weeks ago, and it's O(1) to update per attempt — the teacher dashboard stays fast as usage grows instead of re-scanning every historical attempt.
  • Provider-agnostic LLM adapter — one function (_complete()) normalizes Groq's and Anthropic's different request shapes, so the four call sites in the app never branch on provider.

Project structure

pathshala/
├── backend/
│   ├── app/
│   │   ├── main.py                FastAPI app, router wiring
│   │   ├── config.py              All settings, loaded from .env
│   │   ├── database.py            SQLAlchemy engine/session
│   │   ├── models/
│   │   │   ├── models.py          ORM: User, Doubt, PracticeQuestion, Attempt, TopicMastery
│   │   │   └── schemas.py         Pydantic request/response contracts
│   │   ├── routers/
│   │   │   ├── auth.py            Signup / login
│   │   │   ├── doubts.py          Grounded Doubt-Solving Agent
│   │   │   ├── practice.py        Adaptive Practice Generator
│   │   │   ├── insights.py        Teacher-Facing Insight Agent
│   │   │   └── corpus.py          Corpus (re)ingestion, teacher-only
│   │   ├── services/
│   │   │   ├── rag_service.py     Chunking, embedding, retrieval (ChromaDB)
│   │   │   ├── llm_service.py     Provider-agnostic LLM adapter (Groq / Anthropic)
│   │   │   └── mastery_service.py EMA mastery tracking, weak-topic queries
│   │   ├── utils/
│   │   │   ├── security.py        Password hashing (bcrypt), JWT
│   │   │   └── deps.py            Auth dependencies (get_current_user, require_teacher)
│   │   └── data/
│   │       └── corpus/            Subject-organized source material (see below)
│   ├── scripts/
│   │   ├── ingest_corpus.py       CLI: rebuild the vector index
│   │   └── seed_demo_users.py     CLI: create demo teacher/student accounts
│   ├── requirements.txt
│   └── .env.example
├── frontend/
│   ├── src/
│   │   ├── pages/
│   │   │   ├── AuthPage.jsx           Login / signup, with one-click demo fill
│   │   │   ├── DoubtsPage.jsx         Ask-a-doubt UI with citation "margin notes"
│   │   │   ├── PracticePage.jsx       Adaptive MCQ practice flow
│   │   │   └── TeacherDashboard.jsx   Class heatmap + attention list
│   │   ├── components/TopNav.jsx
│   │   ├── AuthContext.jsx        Session state (JWT in sessionStorage)
│   │   ├── api.js                 Typed fetch client for the backend
│   │   ├── App.jsx                Routing, role-based landing page
│   │   └── styles.css             Design tokens ("ruled textbook page" system)
│   ├── package.json
│   └── .env.example
├── demo_video_script.md           Timed 3-speaker script for the submission video
└── README.md                      You are here

Quickstart (local)

Requirements: Python 3.11+, Node 18+, a free Groq API key (or an Anthropic key, if you have credits).

1. Backend

cd backend
python3 -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate
pip install -r requirements.txt

cp .env.example .env

Edit .env — default provider is Groq (free tier):

LLM_PROVIDER=groq
GROQ_API_KEY=gsk_...          # get one free at https://console.groq.com/keys

Or switch to Anthropic if you have credits:

LLM_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
LLM_MODEL=claude-sonnet-4-6

Everything else has a working zero-cost default. Then:

python scripts/seed_demo_users.py     # creates teacher@pathshala.demo / student@pathshala.demo, password: demo1234
python scripts/ingest_corpus.py       # indexes backend/app/data/corpus/ into the local vector store

uvicorn app.main:app --reload --port 8000

Backend is now live at http://localhost:8000. Interactive API docs (auto-generated by FastAPI) are at http://localhost:8000/docs — useful for judges who want to poke the API directly without the frontend.

2. Frontend

In a second terminal:

cd frontend
npm install
cp .env.example .env.local        # default already points at localhost:8000
npm run dev

Frontend is now live at http://localhost:5173.

3. Log in

Use the demo accounts seeded in step 1 (password demo1234 for both), or sign up fresh from the UI:

  • teacher@pathshala.demo — lands on the class dashboard.
  • student@pathshala.demo — lands on the ask-a-doubt page.

4. See it work

  1. As the student, ask: "Why do passengers fall forward when a bus stops suddenly?" (subject: Physics). Watch the citation appear underneath, pointing at the exact source passage.
  2. Go to Practice, leave the topic blank on your first round (type "Newton's First Law" to seed it), answer a couple of questions — deliberately get one wrong.
  3. Generate practice again with the topic blank. Notice it auto-selects the topic you got wrong, at an easier difficulty.
  4. Log in as the teacher. The class heatmap and the "needs attention" list now reflect that attempt in real time.

Adding real textbook content

The repo ships with three original, hand-written subject notes (Physics — Newton's Laws, Mathematics — Quadratic Equations, Biology — Photosynthesis) under backend/app/data/corpus/<Subject>/ so the prototype is fully runnable and demoable out of the box with zero setup.

To point PATHSHALA at real open-licensed textbook content (e.g. NCERT, which publishes textbooks under an open license for educational use):

  1. Download the relevant chapter PDFs.
  2. Drop them into backend/app/data/corpus/<Subject>/ (create the subject folder if it doesn't exist — the folder name becomes the subject tag used everywhere in the app).
  3. Re-run python scripts/ingest_corpus.py, or hit Rebuild knowledge base on the teacher dashboard — ingestion is idempotent, so re-running it is always safe.

Both .pdf (page-numbered citations) and .txt (source-only citations) are supported.


Deploying (optional, for a hosted prototype link)

Zero-cost hosting is possible in the same spirit as local dev:

  • Backend — Render or Railway free tier. Set GROQ_API_KEY (or ANTHROPIC_API_KEY) and JWT_SECRET as environment variables. SQLite works for a demo; for anything beyond that, set DATABASE_URL to a managed Postgres instance (e.g. a free-tier Supabase or Neon database) — the code requires no changes, SQLAlchemy handles both identically.
  • Frontend — Vercel or Netlify free tier. Set VITE_API_BASE_URL to the deployed backend URL.
  • Vector store — ChromaDB persists to a local disk directory (app/data/chroma_store/). On most free-tier hosts this directory is ephemeral across deploys — re-run ingestion after each deploy, or mount a persistent volume if the host supports one.

If no live link is available at judging time, the local-run instructions above are complete and sufficient — every step has been verified against a real running instance of both servers.


Known limitations and honest next steps

Being direct about these matters more than pretending they don't exist:

  • Schema migrations — tables are created via Base.metadata.create_all() on startup, fine for a hackathon timeline but a real deployment needs Alembic for versioned migrations.
  • Topic labels are LLM-generated free text, not a fixed taxonomy — two questions on the same concept could get slightly different topic strings (e.g. "Newton's First Law" vs "Newton's 1st Law of Motion"), which would fragment mastery tracking. A production version would normalize against a fixed syllabus topic list per subject.
  • Practice generation retrieves the top-K chunks for a topic every time, which tends to pull the same passages when the same topic is requested, reducing novelty across repeated practice rounds. The fix is to remember which chunks were already used per student and vary retrieval away from them.
  • No offline/low-bandwidth mode yet — relevant for the same under-resourced-school context this problem statement targets. A production version would cache the last N answers client-side and support a low-data mode.
  • Single-language demo corpus — preferred_language is already wired through the schema and the prompt (respected by llm_service.synthesize_grounded_answer), but the demo corpus itself is English-only. Multilingual answers work today for any language the LLM supports, but retrieval quality across languages depends on how multilingual the underlying embedding model is, which all-MiniLM-L6-v2 only partially is. Swapping to a multilingual embedding model (e.g. paraphrase-multilingual-MiniLM-L12-v2) is a one-line config change for real multilingual deployment.
  • Groq free-tier rate limits — fine for a live demo, but tight compared to paid tiers. If you're stress-testing with large batch sizes during development, you may see occasional 429s; not a defect in the app.

Judging criteria — where to look

Criterion Where
Innovation Grounded RAG (not prompt-stuffed) doubt-solving with visible, checkable citations; mastery-driven adaptive difficulty; teacher dashboard fed by the same signal as the student experience — one coherent loop, not three demos.
Technical implementation backend/app/services/rag_service.py (real vector search), mastery_service.py (EMA update rule), llm_service.py (provider-agnostic adapter), role-gated JWT auth, defensive LLM-output parsing.
Feasibility Runs today on a laptop with a free-tier deploy path; zero infra cost beyond generation, and even that defaults to a free tier.
Scalability ChromaDB + SQLite swap cleanly to a managed vector DB + Postgres with no code changes beyond DATABASE_URL — see Deploying.
Code quality Typed Pydantic schemas end-to-end, service/router separation, inline rationale comments at every non-obvious design decision (not just what the code does, but why).
Documentation This file, plus the accompanying setup guide document.
Presentation See demo_video_script.md for the recommended 3-speaker walkthrough structure.

Team

Built by [FORNAX] — PSIT, Kanpur — for OOSC 4.0.

Name Focus area
[Siddhima Tiwari] Backend / RAG pipeline
[Chandni Singh] Frontend / product design
[Devansh Singh] Data model / mastery logic / demo

License

MIT — see LICENSE. Free to use, modify, and build on.

About

AI tutoring that shows its sources. RAG-grounded doubt-solving, adaptive practice, and a live teacher dashboard — built for OOSC 4.0.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages