Case study · № 122026WeMakeDevs · Cognee

ParikshaMind

An adaptive quiz tutor for Indian government exams whose defining feature is persistent cross-session memory, powered by a self-hosted Cognee graph + vector store. It greets returning learners with what they scored last time, drills their weak topics, and retires topics they've mastered so they're never re-tested.

RoleSolo
MemoryCognee
LLMGroq 70B
TrackOpen-source
parikshamind · memory graph
ClientAPIMemoryStores & LLMReactViteFastAPIsession · answer · progressCogneeremember · recall · improve · forgetfastembedlocal · 384-dimQuestion bankpre-generatedSQLite · LanceDB · Ladybugrelational · vector · graphGroqLlama-3.3-70Bservereason
Fig. 1 · Memory-first tutor — FastAPI over self-hosted Cognee (SQLite + LanceDB + Ladybug graph); Groq reasons, and a pre-generated bank keeps quizzes instant.
01

Context

50M+ Indians grind government exams — UPSC, SSC, state boards like Gujarat’s GSSSB — on textbooks and YouTube. Every AI tutor forgets them the moment the chat ends: it re-asks material they’ve mastered, has no memory of their weak spots, and no sense of progress. The thesis of ParikshaMind is that memory across sessions is the missing differentiator, not a bigger model.

Built solo inside the WeMakeDevs hackathon’s open-source, self-hosted Cognee track.

welcome back · recall
02

Approach

A FastAPI backend imports Cognee directly and owns every memory call against a fully self-hosted store — SQLite for relational, LanceDB for vectors, and a Ladybug graph, all local and file-based. Each of Cognee’s branded APIs does visible work: remember() ingests the syllabus and each quiz result into a per-learner dataset; recall() pulls a concise mastery summary at session start; search() with graph completion generates syllabus-grounded MCQs; improve() re-weights the learner’s graph after a session; forget() wipes it on request.

Per-learner isolation is just a user_<id> dataset, so re-entering the same name across a refresh recalls prior performance. Embeddings run locally via fastembed — no key, no cost.

graph + vector store
03

The token-frugality problem

The build started on Gemini 2.5 Flash, but the free key capped at ~20 requests a day — unusable for a live demo. I switched the reasoning LLM to Groq’s llama-3.3-70b-versatile free tier via litellm, rate-limited in config.

The real fix was structural: quizzes are pre-generated once, offline, into a question bank and served instantly at runtime, so the only tokens spent live are the light recall() call. The tutor feels instant and costs almost nothing to run.

pre-generated bank
04

Decisions & tradeoffs

  • Cognee over rolling my own memory. A hybrid graph + vector store keyed per learner is exactly the shape this problem needs; reimplementing it would have burned the whole week.
  • Pre-generated bank over live generation. Instant quizzes and near-zero runtime cost, at the price of variety per topic — a good trade for a memory demo, not for production.
  • Groq over Gemini. Forced by a rate cap mid-build. Worth stating plainly: the shipped tutor runs on Groq, even though older planning docs still say Gemini.
05

Honest scope & what I would change

A “mastery map” graph visualization was planned for the last day and didn’t ship —/progressreturns a text summary and a mastered-topics list, not a rendered graph. That’s the first thing I’d finish. After that: move the per-process session store into Cognee itself so runtime state survives a restart, and widen the question bank so mastery is earned across more variety, not the same eight questions per topic.

Built with
ReactVitePython 3.12FastAPICogneeLanceDBLadybug (graph)Groq Llama-3.3-70Blitellmfastembed
← PreviousSwasthyaSetuNext →Vansaarthi
You found the trick.
Thanks for
looking closely.
↑ ↑ ↓ ↓ ← → ← → B A · konami