Back to projects

Retrieval-Augmented Generation Chatbot

ChatGJU

Nov 2025 – Mar 2026github.com/ChatGJU ↗

A RAG chatbot that answers questions about the German Jordanian University from roughly a thousand indexed web pages and departmental documents. My graduation project, built and led by a team of four.

About the project

GJU students depend on information scattered across dozens of department pages, PDFs, and offices: admission rules, registration deadlines, exchange programs, exam schedules. Finding a clear answer usually means digging through the university website or asking around in student group chats.

ChatGJU is a graduation project that fixes this. It combines a scraped index of around 1,000 university web pages with a curated question-and-answer knowledge base, and uses retrieval-augmented generation to answer student questions in natural language, in Arabic or English, with answers grounded strictly in university sources.

The project was built as a monorepo with a team of four over one semester. I led the team, owned the overall architecture, and coordinated and reviewed everyone's integration work while contributing across the stack.

01

One backend, every chat surface

The core architectural decision was a strict separation between the brain and the faces. A Python FastAPI backend (apps/retriever) exposes three endpoints: a health check, a retrieve-only endpoint for vector search, and a chat endpoint that runs the full RAG pipeline.

Every chat interface, the Next.js web app today, and the WhatsApp bot and mobile app planned next, talks to that single API with a standard messages payload. Adding a new surface means building a thin client, not a new brain.

The web frontend is a clean Next.js and TypeScript chat interface with conversation history, streaming-style typing states, and source metadata returned alongside each answer.

02

The retrieval pipeline

Questions go through a full pipeline before the language model ever sees them:

Detect the question's language, embed it with Cohere's embed v4.0 model at 3,072 dimensions, search the Zilliz (Milvus) vector database for the top candidate chunks, then re-rank using source-type boost weights and cut off anything below a minimum confidence score.

On top of that sit two retrieval refinements I'm particularly happy with: a heuristic that detects list-style questions like "list all engineering programs" and widens the search for better coverage, and a query-intent service that infers structured department filters from natural language, so a question about the CS department only searches CS-tagged content.

03

Grounding and anti-hallucination

A university chatbot that invents deadlines or office locations is worse than no chatbot. The system prompt enforces strict grounding rules: answer only from the retrieved knowledge base excerpt, never invent numbers, dates, emails, or links, and say when the knowledge base doesn't contain the answer.

Off-topic questions get politely redirected to university topics, and retrieved chunks carry rich metadata (title, domain, source type) into the prompt so the model can be precise about what it cites.

We also built an evaluation tool that runs question sets against the pipeline, so prompt and retrieval changes are measured instead of guessed at.

04

Data pipeline and leading the team

A scraper crawls gju.edu.jo into structured CSV, and separate ingestion scripts load both the scraped content and hand-curated Q&A into the vector database with consistent tagging. Keeping ingestion separate from scraping let us rebuild the index without re-crawling.

As team lead I coordinated tasks across four people, reviewed all integration work, and owned the architecture end to end. That meant writing clear interface contracts early (the API shape never changed mid-semester), and making sure the backend, frontend, and data workstreams came together instead of drifting apart.

What came out of it

Next.jsTypeScriptFastAPIPythonZilliz / MilvusCoherePyMilvus

Want to dig into the code or the details?