Lakshya: the academic assistant and CO tracker
Inspiration
Every engineering college in India that goes through accreditation has to show Course Outcome (CO) attainment: for each course, how well students achieved each learning outcome. In most departments, faculty still build this by hand. They mark quizzes, copy scores into spreadsheets, map every question to a CO, and calculate the averages at the end of the semester. It is slow, it is easy to get wrong, and it only tells you about a weak outcome after the semester has finished.
We asked a simple question: what if the CO sheet built itself while teaching was happening, and the weak outcomes were visible while there was still time to fix them? That became Lakshya (Sanskrit for "goal").
What it does
- Faculty upload their lecture slides. The AI tags each slide with the COs it covers and drafts multiple-choice questions for each CO.
- Faculty approve every question. Nothing the AI writes reaches a student until a human approves it, and the database refuses to publish a quiz that contains an unapproved question.
- Students attempt a quiz (at most two attempts) and get a score for each CO, a review of each wrong answer with an explanation, and a personal study plan built from their weak COs.
- The CO sheet is computed by plain code, never by an LLM. Faculty see a student × CO table, a class dashboard with weak COs highlighted against the target, drill-downs, and an Excel export.
An agent (faculty chat) can find weak COs, draft a remedial quiz, and propose a schedule. Anything that changes data is only a proposal until the faculty member confirms it.
How we built it
Backend: FastAPI with SQLAlchemy Core on Supabase Postgres. Login uses bcrypt-hashed PINs and passwords and JWTs with the role in the token. The backend runs in Docker on Render.
The database enforces the rules, not just the code. Triggers block unapproved questions from published quizzes. Checks and unique keys limit each student to two attempts per quiz. Row-level security is on for every table, and default privileges are revoked for the public API roles.
Grading and CO math are plain code. A student's score for a CO is $$\text{CO score} = \frac{\sum \text{marks obtained}}{\sum \text{maximum marks}} \times 100$$ taken over the counted attempt, using a configurable rule (best, latest or average). A CO is flagged weak when the class average falls below its target.
AI: quiz generation, slide tagging and the agent run on Nebius Token Factory using NVIDIA Nemotron models. [CONFIRM with Danwin: Nemotron 3 Nano for tagging, Nemotron 3 Super for question generation and the agent, and whether Ultra is used.] Token usage for every call is logged to the database and shown on a usage page.
The agent runs a capped tool loop. The user and role always come from the server session, so a student can never ask for another student's data. Writes go through a propose-and-confirm step with an expiry.
Frontend: built with Lovable (TanStack Start) and connected to the API. [CONFIRM: describe what is wired at submission time.]
Tests: more than 125 backend tests run against a real Postgres database. They cover the DB constraints, student data isolation, the attempt rule, and the agent's role checks.
Challenges we ran into
A merge silently deleted working routes. A conflict resolution kept the empty version of a file, and the quiz endpoints vanished. The tests caught it as a wall of 404s, and we restored the routes and added checks on the route table.
Reasoning models spend tokens before they answer. Nemotron used 22 reasoning tokens to answer a one-line prompt. A study-plan call stopped at exactly 900 tokens, which was our cap, so the model's text was dropped and a default was used. We learned to size token budgets for reasoning and to log why a call falls back.
Security under time pressure. We locked the database down with row-level security, found default privileges that would have exposed future tables, and fixed them in a migration. We also audited the git history for leaked secrets before making the repo public.
Shared database, flaky tests. Three people running tests against one database produced duplicate-key failures from leftover rows. We moved to unique per-test data and cleanup that only deletes the rows a test created.
Small clock differences broke login. A token issued a fraction of a second "in the future" was rejected, so we added a short leeway.
What we learned
Let AI generate, and let humans and code decide. The most valuable design choice was a hard line: the LLM drafts, the faculty approve, and plain code does the math.
Put rules in the database. A rule enforced only in application code is one refactor away from being broken. The triggers and constraints caught real mistakes.
Test the boundaries, not just the happy path. Cross-student access, unknown IDs, expired proposals and wrong roles were where the real bugs lived.
Reasoning models change the economics of a call. Latency, token caps and parsing all behave differently, and the usage logs paid for themselves.
What's next
Faculty-configurable CO targets and thresholds for each course.
Embedding-based retrieval for slide Q&A (we currently use keyword scoring).
Export of the CO sheet in the university's own accreditation template.
A student-facing agent for study help, with the same session-bound safety rules.
Built with
FastAPI · Python · SQLAlchemy · PostgreSQL (Supabase) · Docker · Render · Nebius Token Factory · NVIDIA Nemotron · TanStack Start · Lovable · pytest
Built With
- fastapi
- nebuis
- python
- render
- superbase
- vite
Log in or sign up for Devpost to join the conversation.