← Portfolio
MSc CS artefact · University of Chester · 2025–26

A support assistant that answers before it invents.

The 2YM Chatbot serves two clients from one system: students get accurate master's-programme answers in seconds, and programme leaders get the repetitive workload deflected, backed by a knowledge base that grows as it runs. When it isn't sure, it escalates to staff rather than hallucinating. Built, deployed, and evaluated with real cohorts by one person, as the placement-year substitute for my MSc.

9.4s
Median first response
vs ~2-day staff wait
33.3%
Wouldn't have asked a human
hidden demand captured
67.9%
Resolved without staff
across 196 live turns
9.8%
Escalation, closing week
down from 17% as corpus learned
~£1.01
Total external cost
whole project lifetime
01How it works

Most questions never reach a language model. Each query is embedded locally with nomic-embed-text via Ollama and matched against a Qdrant vector store. If the best FAQ match clears an empirically-set 0.65 confidence floor, that vetted answer grounds the reply. Below it, the bot asks a clarifying question or routes the query into a staff queue. It never guesses. DeepSeek is called only for a few lightweight steps per message; retrieval itself, and the avatar's emotional tone, run with no model call at all.

Retrieval and decision flow A user question is expanded, embedded locally, and searched against a Qdrant vector store. If the best match scores at or above 0.65 it grounds a persona answer; below that, the bot clarifies or escalates to staff. User question Query expansion (DeepSeek) Embed: Ollama nomic-embed Qdrant top-k search Best FAQ score ≥ 0.65 ? < 0.65 ≥ 0.65 Clarify / escalate to staff queue Grounded answer DeepSeek persona

LLM calls per message: query expansion · persona answer · emotion classify. Retrieval and avatar tone use no model at all

02Two clients, one system

One retrieval mechanism serves both sides at once: the vetted answer a student receives is the repetitive question a programme leader no longer has to field. Student value is measured from the closing test; staff value from the live production log.

Everyday beneficiaries

Students

  • 9.4s median first answer, any time, versus a ~2-day staff wait
  • 33.3% would not have asked a human at all: demand that was previously invisible
  • 4.11/5 helpful, and 4.17/5 as comfortable as asking a person
  • 83.3% said their question was fully answered
Primary operational users

Programme leaders

  • 67.9% of turns resolved without any staff involvement
  • A corpus that compounds: the top 10 answers absorb 63% of demand, and escalations fell from 17% to 9.8% across the test as gaps closed
  • Curate the knowledge base via a role-gated admin panel: approve, reuse, or reject with a reason
  • Insight back to the programme: the log surfaced placement security as the student anxiety hotspot
What's evidenced vs pending

The staff-side value above comes from the live production log, not a projection. Two teacher instruments remain pending, an expert answer-quality rating and a workload survey, both deployed but unreturned at the data freeze. Naturalness also lagged at 3.72/5 ("ChatGPT-like"). Nothing here is overstated.

03Responsible by design
No hallucination
Sub-threshold matches escalate or clarify instead of inventing an answer, which is the behaviour students singled out for praise.
Safety branch
Messages classified as distressed route only to vetted referral content, never LLM-generated wellbeing text.
Deterministic emotion engine
Avatar tone was refactored out of a flaky LLM call into a pure, unit-tested rule engine: 7 user emotions map to 8 avatar tones with layered overrides. Faster, cheaper and testable.
Role-based access
Separate Public, Teacher, and Researcher roles. The read-only Researcher dashboard sits behind TOTP and a Tailscale-only port, isolated from public traffic.
04Built with
Backend
Go (stdlib)PostgreSQLsqlc
Retrieval
Ollamanomic-embed-textQdrantDeepSeek
Frontend
Go templatesReactTypeScriptTailwind
Infra & security
DockerHetzner VPSnginxTLSRBACTOTPTailscale

Solo development, multi-stakeholder project MSc CS placement-year substitute (module WB7104). Engineered alone, delivered through a 30-week formal reporting cycle with sponsor Dr Alex Fenton, programme-leader users Trina Roberts & Sue Ollerhead and academic supervisor Graham Logan, with scope adapted across seven structured updates. ~848 hours; ~£1.01 total attributable external cost.