Overview

A floating chat widget on this site that lets visitors ask about my career, education, projects, and blog posts in natural language - and nothing else. Most portfolio chatbots either hallucinate freely or need a human to babysit them; the goal here was a small, strictly-scoped RAG system that refuses gracefully outside its domain and never fabricates a source.

Architecture

Ingestion. An admin-triggered "Rebuild Knowledge Base" action pulls content directly from the site's own data layer - career entries, project descriptions, published blog posts (including markdown reports resolved from file), and a static bio/education document. Each source is chunked into ~1000-character passages, embedded with OpenAI's text-embedding-3-small, and upserted into a Pinecone serverless index alongside metadata (title, source type, and a real internal URL for citation).

Query flow. A question is embedded and matched against the index via cosine similarity. If the best match falls below a confidence threshold, the system returns a canned refusal without ever calling the chat model - cheaper, faster, and immune to prompt-injection tricks that rely on the model seeing the question at all. If the match is strong enough, the retrieved passages are passed to gpt-4o-mini inside a system prompt that restricts it to answering only from that context and explicitly instructs it to ignore any embedded instructions trying to override those rules.

Citations are never model-generated. The source list returned to the user is built programmatically from the retrieval results own metadata, not asked of the LLM - so a citation can never point to a page that wasn't actually used to answer the question.

Guardrails

  • Input length caps and a per-IP rate limit (Flask-Limiter) to control cost and abuse on a public, unauthenticated endpoint.
  • A similarity-threshold gate that turns away off-topic questions before they reach a paid model call.
  • A system prompt hardened against prompt injection embedded in the user's question.
  • Deterministic, retrieval-derived source citations on every substantive answer.

Result

A visitor can ask "What projects have you built with multi-agent RAG?" and get a synthesized answer citing the specific project and blog pages it drew from - while a question like "what's the capital of France?" is refused outright, before it ever reaches OpenAI.

Ask about my work

Ask about my career, education, projects, or blog posts.