santifer/cv-santiago: The CV That Behaves Like a Production AI System

An interactive portfolio that turns a personal resume into a live demo of agentic RAG, voice latency control, security defenses, and eval-driven LLMOps.

8 min read • View on GitHub • More from santifer

A paper CV lies on a desk while a magnifying lens, retrieval drawer, voice waveform meter, and security fence inspect it like a machine under test. The scene explains that this portfolio treats a resume as an operational system, not a static document.
The resume is the interface. The real product is the system that audits, retrieves, defends, and measures it.
Key Takeaways

A CV That Proves Itself

Most portfolios describe capability. santifer/cv-santiago does something sharper: it demonstrates capability in the product itself. The CV is not the point. It is the front door to a system that can be queried, stress-tested, traced, and defended like a real AI application.

A production-grade interactive portfolio that **demonstrates the skills it describes**

Santiago Fernández de Valderrama, Creator and Maintainer · santifer/cv-santiago README.md

That inversion matters. A static CV can list RAG, voice, observability, and security. It cannot show whether those claims survive a hostile prompt, a slow retrieval path, or a real evaluation gate. This repo answers those questions by making the portfolio itself the test harness.

Why a Static Portfolio Was the Wrong Shape

A conventional portfolio optimizes for presentation. This one optimizes for evidence. It is built for the question hiring managers and technical peers actually care about: can this person ship an AI product that behaves well under pressure?

CapabilityStatic portfolioBasic chatbot embedsantifer/cv-santiagoReal LLMOps app
InteractivityRead-only pagesSingle chat boxText and voice, with portfolio contextMulti-surface product experience
Retrieval qualityNoneUsually none or naiveHybrid search with rerankingRetrieval tuned through traces and evals
Safety layersManual content controlMinimal filteringMulti-layer defense against injectionDefense-in-depth with monitoring
ObservabilityPage analyticsOften absentLangfuse traces, costs, and ops viewsProduction telemetry and debugging
Eval loopNoneRare71 automated evals and CI gatingContinuous quality checks
ForkabilityLooks polishedSometimes copyableFully open and inspectableUsually internal and complex

The point is not that this repo is bigger. It is that the extra machinery is aligned with proof. Every added layer answers a failure mode that a normal portfolio never exposes.

The Chatbot Is a Stack, Not a Widget

The chatbot is the core exhibit, but it is not a toy. It starts with a tool decision, then moves through hybrid retrieval, reranking, generation, tracing, and cost accounting. The architecture is split so text and voice can share business logic while still taking different paths when constraints differ.

The system chooses depth based on mode and latency. Text can afford more reasoning. Voice has to stay within a tighter timing budget.

A close-up of two diverging pipelines where a fuller reasoning lane passes through retrieval and reranking, while a faster lane skips ahead when time is tight. The image explains that the chatbot changes behavior based on interaction mode and latency budget.
The interesting design choice is not retrieval itself. It is when the system decides to use less of it.

That duality is the real product insight. Text mode can afford a richer reasoning chain. Voice mode cannot, because human speech punishes hesitation. So the system adapts, not just by swapping output formats, but by changing how much work it does before it speaks.

// Pseudocode for the latency-aware voice path
if (mode === 'voice') {
  const results = await searchDocuments(query, { timeout: 1500 });
  if (results.timedOut) {
    return fallbackToRawChunks(results.partialContext);
  }
  return generateWithRerank(results.context);
}

return generateWithRerank(await searchDocuments(query));

The Voice Mode Has a Different Constraint: Time

This is where the project stops feeling like a chatbot and starts feeling like an engineered interface. Voice interaction is governed by latency budgets, so the system is willing to sacrifice depth when retrieval takes too long. That is a product decision expressed as architecture.

In practice, that means the pipeline can degrade gracefully. Instead of waiting for the perfect answer and missing the conversational moment, it returns something usable, then keeps the experience alive. That choice is subtle, and it is exactly the kind of trade-off strong AI product teams have to make.

Security Is Built In, Not Added Later

The security story is unusually serious for a personal portfolio. The README describes a 6-layer defense, and the implementation reflects the same mindset: detect risky intent, protect system instructions, watch for canary leaks, and alert when something looks adversarial.

AI Chatbot "Santi" — Text (Claude Sonnet) + Voice (OpenAI Realtime API). Responds in first person as Santiago. Agentic RAG with hybrid search (pgvector + BM25) and Haiku reranking

Santiago Fernández de Valderrama, Creator and Maintainer · santifer/cv-santiago README.md

This matters because prompt injection is not a theoretical risk here. A public-facing portfolio chatbot invites curious, weird, and sometimes hostile inputs. Treating defense as part of the feature set, rather than an afterthought, is what makes the repo credible as a production demo.

LLMOps, but for One Person

The private ops layer is the quietest part of the project and maybe the most important. It tracks traces, costs, performance, and evaluation signals so the system can be inspected like a product in active use. That is the difference between a flashy prototype and an artifact of engineering discipline.

Ops primitiveWhat it doesWhy it matters here
TracingCaptures steps across tool use, retrieval, and generationMakes failures inspectable instead of mystical
Cost accountingEstimates the dollar cost of messages by modelForces the team to see the economics of every interaction
EvalsChecks factuality, persona, safety, and retrieval qualityTurns quality into a gate, not a vibe
Closed loopCan turn weak production traces into new testsLets the system improve from real failure modes

The closed loop is the thesis-level move. When traces can generate tests, the portfolio is no longer just documenting skill. It is manufacturing more skill evidence over time. That is unusually mature for a personal site, and it is why the repo feels more like a product team in miniature.

What Makes It Different From Other Portfolios

Compared with static portfolio generators, this repo has state, memory, and behavior. Compared with a basic chatbot embed, it has retrieval quality, safety, observability, and a fallback strategy. Compared with no-code chatbot platforms, it is open, inspectable, and forkable. Compared with most LLMOps demos, it has a real user-facing purpose.

QuestionMost portfolioscv-santiago
Does it prove skill or only list it?Mostly lists itIt proves it through the app itself
Can it survive adversarial input?Rarely testedBuilt with layered defenses
Can it explain its own answers?Not reallyYes, through retrieval and tracing
Can it adapt to voice latency?Usually not applicableYes, with a fast fallback path
Can you inspect the system end to end?Usually noYes, from UI to ops to evals

That is the real differentiator. The repo is not trying to be the prettiest CV on the internet. It is trying to be the most believable evidence that the builder can design, ship, and operate an AI system.