A few months ago, one question kept nagging at our team: what if every student had a tutor that never got tired, never got annoyed, and always had their exact textbook open in front of them?
We didn't want to build another generic chatbot. Ask ChatGPT or Gemini directly to "explain HSC Physics" and you'll usually get something generic — not aligned with the actual curriculum, and often pulling context from the wrong place entirely. We wanted a system that genuinely reads a student's own textbook and answers in that book's language, grounded in that exact chapter's context. That was the starting point for Progga (progga.bd).
In this post, I'll walk through the technical decisions we made, where we got things wrong early on, and how the current architecture came together.
The Actual Problem
NCTB textbooks and the popular HSC textbooks from major Bangladeshi publishers mostly exist as PDFs. Feeding these PDFs directly into a vector database causes some very specific problems:
Chapter structure (headings, sub-headings, example boxes) gets destroyed
Tables and formulas turn into garbled text
A single chunk ends up mixing content from two unrelated topics, which drags the wrong context into retrieval
Our first prototype made exactly this mistake — extracting raw text from PDFs, chunking it naively, and ingesting it straight into the vector store. The result: the RAG pipeline frequently pulled answers from the wrong chapter, or stitched together half-formed sentences into an answer that read as confident but was subtly wrong.
The Fix: Converting Every Textbook to Clean Markdown First
We changed course. Every textbook was converted into clean, chapter-by-chapter Markdown documents — preserving headings, sub-topics, worked examples, and figure captions — before any of it touched the embedding pipeline. Three things improved immediately after this change:
Retrieval accuracy jumped noticeably, because chunk boundaries now followed the actual chapter/topic structure instead of an arbitrary character count.
Semantic search became far more context-aware — a query would now pull back a coherent topic unit instead of half a paragraph.
It became much easier to separately tag formulas, examples, and real-world applications — which later became the backbone of our "Formula Sheet" feature.
Looking back, this single decision probably had the highest ROI of anything we did on this project.
Choosing the Vector Database and Embedding Model
For embedding and retrieval, we settled on:
Pinecone as the vector database — it kept ops overhead low as we scaled, and metadata filtering (by grade, subject, chapter) was straightforward to implement.
Jina Embeddings for text embedding. Our textbooks are a mix of English terminology and Bangla explanation, and Jina's performance on that kind of mixed-language content held up noticeably well.
One important trick here: we don't just run a raw similarity search. We first filter by grade + subject + chapter metadata, and then run semantic search within that narrowed subset. This significantly reduces the risk of a topic with the same name from a different grade's textbook surfacing incorrectly.
The Generation Layer: LangChain + Gemini
Once retrieval brings back the right chunks, the next step is turning them into a coherent, grade-appropriate answer. We use LangChain for orchestration, with Google Gemini as the generation model.
A few things were non-negotiable here:
Explicitly passing the student's grade level into the prompt, so the same question gets simplified differently for a Class 6 student versus an HSC student.
Keeping source attribution — tracking exactly which chapter/section an answer came from. This matters a lot for the "Study Workspace" feature, where a student uploads their own notes and chats with them; the system needs to answer strictly from that uploaded material and not from general world knowledge, to keep hallucination in check.
Building honest fallback behavior — when retrieval doesn't surface enough relevant context, the system should say "I'm not confident about this topic" rather than confidently generating a wrong answer.
Backend and Infrastructure
The stack ended up looking like this:
Next.js — the frontend, covering the whole student-facing surface (AI Classroom, Chat, Quiz, Flashcards, etc.)
FastAPI — the backend API layer, hosting the RAG pipeline and business logic
PostgreSQL — user data, progress tracking, quiz history, structured content metadata
Redis — **caching plus session/rate-limit management, particularly to keep latency down on quiz generation and chat responses
**Docker — keeping the whole system containerized for consistent deployment
One reason we picked FastAPI was async support. A single request often involves multiple I/O-bound steps in sequence — vector search, an LLM call, a database read/write — and without an async architecture, latency compounds fast.
What's Built on Top of This Pipeline
Once the core RAG pipeline was stable, we layered feature after feature on top of the same foundation:
AI Classroom — read the digitized textbook and highlight any line to ask the AI about it directly
Progga Chat — a subject- and chapter-scoped conversational assistant
Study Workspace — upload your own notes or slides and get answers grounded strictly in that source materialMath Assistant (Onko Bhaiya) — scan a handwritten or typed math problem and get a step-by-step walkthrough
Quiz and Question Bank — generate unlimited MCQs/CQs from any chapter, and analyze past board exam papers to flag which topics deserve the most attention
Formula Sheet and Flashcards — pulled directly from the structured Markdown, so every formula comes with context and real-world application attached
What We'd Do Differently (or the Same) Next Time
A few lessons that would shape how we'd approach a RAG system from day one:
Never ingest raw PDFs directly. Preserving content structure takes more upfront effort, but the impact on retrieval quality is enormous.
Filter by metadata before running semantic search, not after. Relying purely on embedding similarity leaves you exposed to cross-grade or cross-subject context bleeding into answers.
Treat grounding as a first-class concern, not an afterthought. In an education context specifically, the cost of a confidently wrong answer is high — source attribution and honest fallback behavior need to be part of the initial design, not bolted on later.
Closing Thoughts
We believe AI shouldn't just answer random questions — it should make quality education accessible regardless of where a student lives or whether their family can afford a private tutor. Progga (progga.bd) is our small step toward that.
There's still a lot ahead — multi-agent classroom experiences, 3D simulations, an in-browser coding environment are all in progress. Feedback and questions are always welcome.
🚀 Try Progga: https://progga.bd
Top comments (0)