Inspiration
Students already ask AI chatbots for help with homework. The trouble is that a general chatbot doesn't know what their class actually covers. It answers from the whole internet, sometimes goes beyond the syllabus, and sometimes states things that are simply wrong with total confidence. A student can't tell which parts of the answer came from their textbook and which were made up. Things get messy when we try to use too many sources which eventually leads to less knowledge gain because rather solving the issue increases the error.
We wanted a tutor that works the way a good teacher does: it starts from the class material, shows where every point came from, and says so when the notes don't cover something. We also wanted it to run on hardware a school already owns, so student data never has to leave the building.
What it does
Students already ask AI chatbots for help with homework. The trouble is that a general chatbot doesn't know what their class actually covers. It answers from the whole internet, sometimes goes beyond the syllabus, and sometimes states things that are simply wrong with total confidence. A student can't tell which parts of the answer came from their textbook and which were made up.
We wanted a tutor that works the way a good teacher does: it starts from the class material, shows where every point came from, and says so when the notes don't cover something. We also wanted it to run on hardware a school already owns, so student data never has to leave the building.
How we built it
- Backend: FastAPI, PostgreSQL with pgvector, Redis + Celery for background ingestion, Meilisearch, and GoTrue for authentication.
- Frontend: Next.js 15, React 19 and Tailwind 4.
- Local AI through Ollama: Llama 3.1 8B writes answers and questions, Qwen 2.5 7B checks them, and LLaVA reads diagrams. The rest of the pipeline also runs locally: multilingual-e5 for embeddings, a cross-encoder re-ranker, Tesseract OCR (English and Hindi), faster-whisper for speech-to-text and Piper for text-to-speech.
Retrieval. Each question is searched two ways: by meaning (vector search) and by keywords (full-text search). The two ranked lists are merged with Reciprocal Rank Fusion:
$$\text{score}(d) = \sum_{i \in {\text{vector},\, \text{text}}} \frac{1}{60 + \text{rank}_i(d)}$$
A cross-encoder then re-ranks the top excerpts before Llama writes a cited answer.
Grounding check. A second model (Qwen) checks each claim in the answer against the cited excerpts. If fewer than 60% of the claims are supported, the answer is not shown as coming from the material. One model writes, a different model checks.
Knowing what a student knows. Mastery of each topic is tracked with Bayesian Knowledge Tracing. After a correct answer:
$$P(L \mid \text{correct}) = \frac{P(L)\,(1 - P(S))}{P(L)\,(1 - P(S)) + (1 - P(L))\,P(G)}$$
Then learning is applied: \( P(L_{t+1}) = P(L \mid \text{obs}) + (1 - P(L \mid \text{obs}))\,P(T) \). Here \(S\) is the chance of a slip, \(G\) the chance of a lucky guess and \(T\) the chance of learning the topic between attempts.
Questions are chosen so a student has roughly a 70% chance of getting them right. This uses an IRT-style target \( b \approx \theta - \operatorname{logit}(0.7) \), and question difficulty is updated Elo-style from real answers. Revision is scheduled with FSRS, which predicts how likely a student is to recall a topic after \(t\) days:
$$R(t, S) = \left(1 + \tfrac{19}{81}\cdot\tfrac{t}{S}\right)^{-0.5}$$
Evaluation. The admin console scores the tutor on a test set (faithfulness, answer relevance, context precision and recall, citation accuracy). It also checks whether personalisation actually helps: simulated students with different profiles take adaptive and non-adaptive quizzes through the real quiz engine, and the two learning curves are compared.
Challenges we ran into
- Making "cited" mean something. Citations alone aren't enough, because a model can cite a page and still say something the page doesn't support. Adding a separate checker model and a minimum support threshold was what made the citations trustworthy.
- Citation matching. Our evaluator first counted "p. 1" as a match for "p. 12". We had to normalise page labels and compare them exactly.
- Fitting in 16 GB of RAM and an 8 GB GPU. Every model had to run locally. We picked 7–8B models and kept the embedder and re-ranker small enough to run on the CPU.
- Two portals, one browser. Students and admins originally shared login cookies, so signing into one portal signed you out of the other. We split them into separate sessions with their own cookies, and made each login page refuse the other kind of account.
- Silent failures. Verification codes sometimes never arrived because the auth server sends nothing for an email that is already registered. Now the app tells the user what happened instead of leaving them waiting.
- Video citations. Linking to a video wasn't enough. Citations now jump to the exact second the answer came from.
Accomplishments that we're proud of
- Every answer can be checked against its source in one click.
- The tutor says "I don't know" when the material doesn't cover a question, instead of guessing.
- Everything, including the AI models, runs on one machine with no cloud API.
- Answer quality is measured, not assumed: there's a built-in evaluation suite with downloadable reports.
What we learned
- Grounding is a pipeline, not a prompt: retrieval quality, re-ranking and an independent check each made a measurable difference.
- Small local models are good enough when the task is narrow and the context is right.
- Learning science (BKT, IRT, spaced repetition) is decades old, well tested and cheap to run, and it pairs very well with LLMs.
- Honest error messages matter as much as features. Most of our bug reports came from things that failed silently.
What's next for IntelliNova
- Running pilots with real classrooms, and fitting the BKT parameters to their answer data.
- Support for more Indian languages, both in OCR and in speech.
- Teacher dashboards that show which topics a whole class finds hard.
- A lighter setup for schools without a GPU.
Built With
- caddy
- celery
- deepeval
- docker
- fastapi
- hugging-face
- llama
- llava
- meilisearch
- next.js
- ollama
- pgvector
- piper
- postgresql
- python
- qwen
- ragas
- react
- redis
- sqlalchemy
- tailwindcss
- tesseract
- typescript
- whisper

Log in or sign up for Devpost to join the conversation.