A portfolio assistant that makes things up is worse than none
A generic AI will happily invent a metric, a client, or a claim, and sound confident doing it. On a page about my own work, that is a disaster.
So I did not want a chatbot. I wanted something that could only tell the truth about what I have actually done, and that would rather stay quiet than guess.
Before building anything, I looked at the ways to get there.
The options, before I wrote a line of code
I mapped the ways to put an assistant on a portfolio
Everything on this list can produce an answer. The differences that matter are what the answer is grounded in, whether it shows its sources, and what it does when it does not know.
| Tool | Grounded in my documents | Cites its sources | Refuses instead of guessing | Cost at rest | What I control |
|---|---|---|---|---|---|
| A generic chatbotan LLM with a system prompt | No, answers from model memory | No | No, it sounds confident anyway | Per token | The prompt, nothing else |
| Prompt stuffingpaste all my docs into the prompt | Yes, until the corpus outgrows it | No | No, it fills the gaps | Pays for the whole corpus per question | The prompt, nothing else |
| Chatbot widgetsChatbase, CustomGPT | Yes, on their servers | Sometimes | Tuned to keep answering | A monthly subscription | Their stack, their rules |
| Managed RAGVertex AI Search | Yes | Yes | Configurable | More than a portfolio needs | The service owns the internals |
| This buildRAG, hand built on Google Cloud | Only my case studies and resume | Every answer links its sources | Says so when it does not know | Scales to zero | Every piece, tuned by hand |
Representative options per approach, from scoping the build. The behaviour I could not buy anywhere was principled refusal.
The call
Why I built it by hand
The widgets get you a chatbot in an afternoon, and every one of them is tuned for the same thing: always answer, keep the visitor engaged. On a page about my own work, a confident wrong answer costs more than no answer. The one behaviour I could not buy was refusal.
So I built the pipeline myself on Google Cloud. Not because RAG is exotic, it is not, but because I wanted the grounding contract in my own hands, the running cost near zero, and the cloud skills earned for real instead of claimed.
Grounded, or quiet
The answer is retrieval augmented generation, RAG. Instead of letting the model answer from its own memory, it first pulls the most relevant passages from my real documents, my case studies and my resume, and answers using only those.
Every answer links the sources it used, so you can check it against the real page it came from. If nothing relevant is found, it says so rather than guessing.
Cite or refuse is not a nice touch here. For a bot speaking about my work, refusing to invent is the whole product.
How it works, on Google Cloud
My documents live in Cloud Storage. A step chunks them and turns each piece into an embedding, a numeric fingerprint of its meaning, using Vertex AI, and stores them in Cloud SQL with the pgvector extension. When a question comes in, the app on Cloud Run embeds it, pulls the closest chunks, and passes them to Gemini with one instruction: answer only from these, cite them, or say you do not have it.
The service choices were deliberate and cost aware. Cloud Run scales to zero, so it costs nothing at rest. I used Cloud SQL rather than the pricier managed option, because at this scale the difference was all cost and no benefit. Access and secrets are handled by IAM and Secret Manager, not by keys sitting in code.
The discipline
Reliable is the hard part
The hard part of RAG is not wiring it up. It is making it reliable. I calibrated the retrieval threshold from real query scores rather than guessing, so genuine questions get answered and off topic ones get refused. I set the model to answer deterministically, so the same question does not flip between answering and refusing. And I kept the answers short, first person, and free of invented detail.
This is the same grounded, cite or refuse pattern from my ServiceNow and dental copilots, rebuilt as a genuinely Google Cloud native system.
Where it stands
The honest result
It is live on this site. You can open the Ask feature and try it, and every answer points back to the real page it came from.
The same engine also powers a private second brain over my own notes and reading, kept behind a login. What this build demonstrates is the part I care about: shipping a real, grounded AI system on the cloud, one that is honest about the limits of what it knows.

