← PortfolioMSc 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.
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.