Portfolio Virtual Assistant - Knowledge-Grounded Chatbot
A knowledge-grounded AI assistant embedded on this portfolio that answers visitor questions about Ayokunmi using only a curated markdown knowledge base.
Business Problem
A static portfolio expects visitors to skim and search for what they want. Recruiters and visitors with specific questions ('is he available for internships?', 'has he built anything with AI agents?') often leave without that answer, and a generic chatbot would happily invent dates, metrics, and employment history that aren't true.
Tools Used
Key Features
- Curated chatbot_knowledge.md file injected into Gemini's system instruction, so the model answers only from facts authored by Ayokunmi - not from its training data
- Strict system prompt enforcing third-person he/him pronouns, friendly-but-professional tone, 1-3 paragraph length cap, and an explicit refusal-with-fallback for out-of-scope questions
- Dedicated hiring/availability rule that surfaces Summer 2026 internship search and contact email when visitors ask about opportunities
- Per-IP rate limiting (15 messages per minute) using Django's cache framework with time-bucketed keys, returning a 429 with a friendly message when exceeded
- Input validation (1000-char max, JSON parse guards, empty-message rejection) and an explicit 503 when GEMINI_API_KEY is missing, so the chat fails gracefully instead of leaking errors
- Vanilla-JS launcher widget (floating button, slide-in panel, suggestion chips, message bubbles) wired into the Django base template so it renders on every page without a frontend framework
My Role & Contribution
Sole designer and builder. Wrote the system prompt, authored the markdown knowledge base, implemented the Django view with rate limiting and graceful fallbacks, designed the chat UI in vanilla JS, and tuned the guardrails (refusal patterns, hiring-question handling, persona consistency).
Biggest Challenge
Preventing hallucination on a topic where the model has zero training data (a specific person). Generic LLMs cheerfully invent details when asked about an individual. Solved with a RAG-lite pattern: hand-authored markdown knowledge file injected into the system prompt, plus an explicit instruction that forces the model to refuse and redirect to email/LinkedIn whenever asked anything outside the documented scope.
What I Learned
Practical AI design is about restraint, not capability. The system prompt, the knowledge boundary, and the refusal behavior do more for product quality than the model upgrade. The same pattern (LLM plus scoped knowledge plus rate limit plus graceful refusal) is exactly what real production AI products run, and it generalizes to any internal docs assistant, product help bot, or FAQ replacement.