I built a RAG chatbot for this portfolio
There's a chatbot in the corner of this site. Ask it about my projects, my stack, my experience — it answers in real time.
Here's how it works.
Why RAG
I wanted visitors to ask questions instead of hunting through sections.
Three options:
- Stuff everything into the system prompt → wasteful, costs scale with content
- Fine-tune a model → expensive, slow, content baked in at training time -
- RAG → cheap, fast to update, only sends relevant chunks per query RAG won.
The stack Knowledge base → markdown files (chunked by ## headers) Embeddings → OpenAI text-embedding-3-small (1536-dim) Vector store → Supabase pgvector + HNSW index Backend → FastAPI on Hugging Face Spaces Frontend → Next.js chat widget, Streams API LLM → gpt-4o-mini, temperature 0.3
How a request flows
- User types a question in the widget
- Backend embeds the question with the same model used during ingest
- Postgres returns the top-5 most similar chunks via cosine distance
- Those chunks + the conversation history + a strict system prompt go to gpt-4o-mini
- The response streams back token-by-token through FastAPI's StreamingResponse, decoded in the browser via res.body.getReader()
I separated content, logic, and presentation into three independent deploys.
- Edit markdown → re-run an ingest.py script → bot reflects new content in seconds. No code deploy.
- Edit backend logic → push to HF Space → Docker rebuilds in ~2 minutes.
- Edit chat UI → push to GitHub → Vercel rebuilds.
Three change cycles, three deploy targets. Content, code, and UI each move on their own clock. That’s where I saw a value for layering. Embeddings cost basically nothing. Effectively free at portfolio scale — worth a chatbot for.