Skip to content
Sangam Gupta
All work

sangamgupta.in

This site: a portfolio built as an AI system, with an agent that answers from my own content and the testing and monitoring around it in public.

Built with Claude Code: I decide what goes on it and try every feature; the assistant writes the code.

Status
Live
Stack
Next.js, TypeScript, Groq, Gemini, BM25, Embeddings, Upstash Redis, MediaPipe, WebLLM, Vercel, GitHub Actions
Links
Ask SangamEverything in the LabSite guide
test questions the agent answers through the live endpoint every week
45
reworded questions retrieved correctly by the hybrid retriever, vs 8/10 for keywords alone
9/10
ways to answer: Groq, then Gemini, then the site's own facts with no model
3

How it fits together

  1. Visitor question
  2. Rate limit and guardrails
    • BM25 over site content
    • Gemini embeddings
  3. Reciprocal rank fusion
    • Groq
    • Gemini
    • Offline answer
  4. Answer with sources

Next.js site whose Ask Sangam agent retrieves passages from the site with BM25 plus Gemini embeddings fused by reciprocal rank fusion, answers through Groq with Gemini as backup, and falls back to answering from the content with no model. Weekly evals, a red-team page, provider telemetry, drift monitoring for the demo models and an MCP server.

The problem

A portfolio is a list of claims that recruiters skim quickly, and an AI chatbot bolted on top is easy to make say things that aren't true. I wanted the site itself to show how I build AI products: grounded, tested, watched in production, and honest about what it doesn't know.

How it was built

  1. Keep every fact in one content folder. The pages, the agent's knowledge, the resume PDF, llms.txt and the MCP tools are all generated from it, so they can't disagree.
  2. Retrieve before answering: BM25 over chunks of the content, plus Gemini embeddings, fused by reciprocal rank fusion. I switched to the hybrid only after it measured at least as well as BM25 on a retrieval eval.
  3. Answer only from the retrieved passages, with sources in a header the page shows. If no model is reachable, answer from the content itself rather than fail.
  4. Try Groq first, then Gemini, recording which provider answered, the time to the first token and every failure. The numbers are public in the Lab.
  5. Run 45 graded questions through the live endpoint every Monday and after any deploy that touches answers: facts, admitted unknowns, off-topic refusals and prompt injections. Smaller deploys run 10 smoke cases to save free model quota.
  6. Put a canary in the real system prompt and let anyone attack it on a red-team page, with pattern checks and an LLM judge; each real break becomes a prompt fix and a new test.
  7. Run the trained models in the browser from exported JSON, checked against scikit-learn, and watch their inputs for drift against the training data with PSI.
  8. Stay inside free tiers: Vercel Hobby limits, long jobs split into parts, and scheduled work in GitHub Actions.

Where it is now

Live, with the report card, telemetry and drift numbers updating on the Lab page.

Ask about sangamgupta.in

Answers come from this case study.