← Writing

The right model is no model

Jul 18, 2026

My portfolio has a chatbot. Ask it what I shipped at Inkitt, whether I'm open to offers, what my stack is — it answers instantly, streams the reply with a typewriter effect, and keeps working with your wifi off.

It makes zero API calls. There is no LLM. There is no backend. The weights are a TypeScript file.

This was the plan, not a fallback. The default move in 2026 is obvious: grab an API key, pipe questions to a model, stream tokens back. And I'm not avoiding AI out of principle — I went all-in on agentic coding in 2025, and Claude Code writes the first draft of most things I ship. I know exactly how easy the wiring would be.

I just didn't need it.

The model is a for loop

HV-1 is a hand-written intent matcher over a curated corpus. About 200 lines. It lowercases your question, folds synonyms ("stack", "tools", "toolbox" all collapse to "tech"), forgives one typo via a Levenshtein distance capped at 2, and scores every intent by how many of its keyword phrases survive in your tokens. Strong phrases count triple. Highest score wins.

interface Intent {
  id: string;
  keywords: string[]; // phrases that count toward the score
  strong?: string[];  // phrases that count triple
  answers: string[];  // variants, rotated so repeats don't repeat
}

function score(tokens: string[], intent: Intent): number {
  let s = 0;
  for (const kw of intent.keywords) s += phraseScore(tokens, kw);
  for (const kw of intent.strong ?? []) s += 3 * phraseScore(tokens, kw);
  return s;
}

That's the entire inference engine. The training data is a corpus file I wrote by hand, each intent carrying a few answer variants so asking twice doesn't sound like a broken record.

Look at what this buys:

  • Instant. No network round trip. The typewriter effect is the only latency, and it's decorative.
  • Offline. Airplane mode, conference wifi — it doesn't care.
  • Deterministic. Same question, same answer. You can test it with plain assertions.
  • Free. Zero marginal cost, forever.
  • It cannot hallucinate my resume. This is the one that matters. An LLM wired to my bio can invent a job I never had — in my voice, on my domain. HV-1 can only say sentences I wrote.

The tradeoff is honest: no open-ended questions. Ask HV-1 about the weather and it shrugs and offers a few suggested questions instead. For a portfolio, that isn't a limitation — it's the spec. Visitors ask maybe a dozen distinct things. What did he ship. Is he available. Where is he based. That's an enum, not open-ended language understanding.

Match the tool to the problem

Somewhere along the way, "add AI" became the reflex answer to every product question, the way "add a microservice" was a decade ago. But a model is a cost, a latency, and a failure mode. You should have to argue it in, not out.

For this problem — a known speaker, a small closed set of questions, answers that must be exactly right — the smallest thing that works is not a compromise. It's a feature. Every property I listed above falls out of the decision to not have a model.

The irony I enjoy most: a real AI built the fake one. Claude Code drafted the synonym map and the first pass of the matcher; I tuned the scoring and wrote every answer. A model that costs money per token produced a model that costs nothing per anything.

And if I'm ever wrong about all this, there's an escape hatch. HV-1 sits behind a ChatProvider interface — one method, ask(question): Promise<ChatResponse> — so a real streaming LLM could slot in without touching a line of UI. The door is there. I walk past it every day.

HV-1 has exactly zero parameters, and every single one of them is correct.

Questions about this one? The terminal twin has opinions — ⌘K