Alex OS is my working proof that RAG over a fully dynamic CMS can think — and my portfolio runs on it.
I couldn't find a creative way to show AI engineering and UX in one place. A static portfolio could list my work, but it couldn't demonstrate it.
Alex OS became the all-in-one answer: content, colours, themes and even the assistant's tone all live in the CMS — Theme DNA styles the site, Voice DNA shapes how Alex speaks. When I want to change anything tomorrow, I edit content, not code.
One caching pass took Alex OS's heaviest data loads from 10.5s to 1.8s.
The assembled answer with its cited sources is shown as a static final state.
A FastAPI reasoning and retrieval layer that sits between the CMS and the public site — grounded answers, journey-aware recommendations, and a relationship-graph reasoning pass, not an open-ended chatbot.
Wrong turns worth keeping
- What I attempted
- An animated character — a visible avatar as the face of Alex OS, answering questions on screen.
- Why it initially made sense
- An assistant with a face felt friendlier and more memorable than a plain chat box.
- What showed it was wrong
- It read as cartoonish. It undercut the seriousness of the engineering it was fronting.
- What I changed
- I dropped the avatar. Alex OS became an interface — the orbit, the journeys, a grounded Q&A panel — and the personality moved into Voice DNA instead of a mascot.
- What improved
- The system reads credible, and the character still comes through in how Alex answers rather than how it looks.
- What limitation remains
- Alex has no visual identity beyond the interface itself — and I've made peace with that.
Architecture
FastAPI service with distinct route groups for ask/surface/recommend/capture/synthesis/admin, a config-driven engine layer (persona resolver, model router, block composer), and a services layer for retrieval, embeddings, and relationship-graph traversal. Reads CMS content over an internal HTTP API rather than touching the CMS database directly.
Decisions
Postgres/pgvector is optional, with a keyword-scoring fallback, so retrieval degrades instead of failing outright. Personas and prompts are config — stored as data, editable without a redeploy — rather than behavior hardcoded in Python.
The retrieval layer carries the most deliberate trade-offs. Content is chunked (roughly 1,800 characters per chunk, with overlap) rather than embedded as one vector per item, and query rewriting handles conversational follow-ups. A hybrid keyword+vector fusion path (reciprocal rank fusion) ships enabled by default; whether it measurably beats plain semantic ranking on this corpus hasn't been benchmarked yet — that's a gap on the retrieval-quality list, not a settled comparison. Each ask-mode has its own minimum relevance score, because "no good answer" is a better result than a confidently irrelevant one.
One bug shaped the design more than any feature request: typing "projects" into the assistant returned exactly one project. The fix wasn't retrieving more items — it was recognizing that naming a content type is a browse intent, not a question, and switching strategy for it: widen the net, boost the named type, drop the diversity cap that Q&A mode needs.
Problem
A static portfolio site can show work, but it can't answer specific questions about it, connect related pieces, or reprioritize itself based on what a visitor actually cares about.
Content
Alex OS is a separate service, not a feature bolted onto the CMS. It reads structured content through the CMS's internal API, retrieves and ranks relevant items, and answers questions using that content as grounding — it doesn't invent facts and it doesn't have its own opinions about what a visitor should see. The three homepage threads (what I've shipped, where I've worked, what I know) influence what it prioritizes when answering, but the assistant doesn't create or control them itself.
Beyond single-item answers, it reasons over the relationship graph — two-hop traversals where the model's stated reasons are persisted, so a connection drawn once becomes a fact it can reuse — and a coach layer folds what it has learned into concrete guidance inside the admin.
Limitations
Production hardening is still an open checklist item per the internal progress tracker — confirming Nginx doesn't expose the service publicly, rate limits on public AI endpoints, and secret handling are noted as unconfirmed rather than done. Synthesis of captured activity is still deterministic — there is no LLM pass over it yet.
Next steps
Close out the hardening checklist; expand automated eval coverage for retrieval quality.
Outcome
Grounded Q&A, journey recommendations, and content surfacing.
How this was built
Built with AI assistance (Claude Code). The architecture, the decisions and the trade-offs are mine; a lot of the implementation was written in pair with the model. I work this way deliberately — it's why one person can run a system this size — and the reasoning behind every call here is documented above.
- Category
- AI & RAG
- Tech stack
- FastAPI
- Python
- Anthropic API
- Postgres
- pgvector
- Metrics
- Source-grounded answers
- Per-call cost tracing
- Role
- Architecture + build
Why I built this
I wanted one place where my AI engineering and my UX taste could prove each other, and I couldn't find a format for it — so I built one. Nothing here is hardcoded: the content, the colours, even the way Alex answers questions comes from DNA I can edit. Being able to change everything tomorrow, without touching code — that's the point.