Skip to content
VD
All projects

AI & NLP, 2026

RAG-Scheduler

A local, privacy-first assistant that answers natural-language questions about a course timetable using retrieval-augmented generation.

Retrieval-augmented generation, fully localno API keysIngest, once per timetableCSV uploadMulterEmbed rowsMiniLM, 384-dHNSWLibindex on diskAsk, per questionQuestion“What’s on Tue?”Embed querysame modelTop-k rowscosine searchOllama LLMgrounded promptAnswer+ source rowsnearest neighboursReact + Vite frontend, Express API: /status, /ingest, /ask

The problem

Timetables in spreadsheets are hard to query quickly. Asking “What do I have on Tuesday afternoon?” should just work — without sending personal data to a cloud API.

What it does

  • Upload a CSV; each row is embedded once with all-MiniLM-L6-v2 and indexed in HNSWLib.
  • Queries retrieve the top-k matching rows and pass them to a local LLM via Ollama as grounded context.
  • REST API with /status, /ingest and /ask; answers return the source rows they were based on.
  • Runs fully offline — no API keys, no per-call cost, no data leaves the machine.

Architecture

  • Frontend: React + Vite with a custom useChat hook owning chat state and a services/api.js layer for backend calls.
  • Backend: Express routes stay thin; services handle embeddings, vector storage, CSV ingestion and the RAG chain.
  • The vector index is persisted to disk so ingestion only happens once per timetable.

Method

  • Embed the user's question with the same model used at ingest time.
  • Return the most similar rows by cosine distance from HNSWLib.
  • Build a prompt that constrains the model to answer only from the retrieved rows.

Lessons and next steps

  • The backend was rewritten from FastAPI to Node.js without touching the frontend, because the REST contract was defined first.
  • Next steps documented in the repo: streaming responses, chat history persistence and PDF/calendar ingestion.

Built with

  • React
  • Vite
  • Node.js
  • Express
  • Transformers.js
  • HNSWLib
  • Ollama
  • Multer