Jonathan Mellette
← All work

Live · qaitrek.com

Q&AI

Think of a character. In twenty-five questions or fewer, it will name them — out of a corpus of roughly nine hundred and ninety. Every question is chosen by expected information gain, computed from a hand-built entropy calculation with no mathematics library underneath it.

How it decides what to ask

Information theory, applied narrowly

At every step the engine holds a probability distribution over the whole corpus. For each candidate question it computes how much that question would reduce the entropy of the distribution — how much uncertainty it removes on average — and asks the one that removes the most. Answers update the distribution. Repeat until one candidate dominates.

The prior is deliberately uniform. A popularity tilt would guess famous entities faster and score better on a demo, and it would make the engine worse at its actual job. That is recorded as a numbered design decision, not left as an accident.

~990entities in the corpus
≤25questions to an answer
2,970JSON cards as the truth substrate
98%pass rate required to deploy

The hard problem

Two characters with identical answers

Some entities are, on every available attribute, the same. A pair of sisters who appear together, do the same things, and differ in nothing the question bank asks about. To a selector optimizing information gain across the whole corpus, no question distinguishes them — so it is a coin flip, forever.

I got this wrong twice before getting it right, and both failures are in the decision log. First I added an interactive clarification phase that asked by name, which worked and felt like cheating; it is disabled, with the code left in place and clearly marked inert so no future reader mistakes it for live. Then I tried a hardcoded confidence-threshold cluster lock, and the log records exactly why no belief-percentage threshold could ever have worked.

What actually worked

Contender information gain. Once the field narrows, stop scoring questions against the entire corpus and start scoring them against the handful of candidates that have actually emerged. A question that distinguishes exactly one entity out of nine hundred has near-zero global information gain and will never be asked — but it is decisive when that entity is one of two remaining. Scoring locally surfaces it at precisely the moment it matters.

How it stays correct

A harness, and a gate that refuses

The engine is regression-tested by playing every curated entity against itself — feeding its own truth values back in as answers and checking the engine arrives at it. Nine hundred-odd full games in under thirty seconds, deterministic, with no model calls and no token cost. Its own documentation enumerates what it cannot detect, which is a level of honesty I would want from any test suite I inherited.

The deploy script will not ship below a 98% pass rate. That threshold started at 90% and I raised it after an engine rebuild came in at 100% — a gate you never fail is not a gate. This project previously ran continuous integration on a hosted service and I retired it, because for one person on one machine the local gate does the same work with a faster loop.

The engine committing, then confirming. Two things worth noticing. It reports confidence before it reports an answer — the belief distribution is the actual output, and the name is just its argmax. And the second frame reads “Subject identified in 12 queries”, against a stated ceiling of twenty-five and a corpus of roughly nine hundred and ninety, which is the page’s central claim demonstrated rather than asserted. The interface is LCARS, stardate in the corner, because a Star Trek engine that looked like a web form would be a worse piece of work.

Honest notes

What this is not

There are no unit tests in the conventional sense — no test framework, no per-function specs. The entire quality apparatus is one integration-level regression harness plus the deploy gate. For a system whose behavior is emergent across the whole corpus I think that is the better instrument, but it is a different claim than "unit tested" and I would not let it be mistaken for one.