Trying out NanoGPT

I promised I'd try it out!


I have taken out a NanoGPT subscription! From what I can tell, I have a much wider variety of models, but some aren’t too reliable - especially niche ones or fine tunes, where a single provider being overloaded means either horrible TTFT or TPS, or outright failures. Popular models are a bit better, but I’m getting worse TPS empirically.

Image generation works as promised, though the models seem a bit older. They really don’t distinguish between cached and uncached, or largely even model selection aside from 1x and 2x usage models. Their privacy guarantees are a bit weird, since enabling ZDR only on the API key allows Muse Spark Contributor - specifically a non-ZDR training allowed endpoint. Apparently closed models and single provider models aren’t included in that toggle. But they do put text in the description of any model if it has limited privacy guarantees, and apparently automatic routing only uses FP8+ no-train providers.

I’ll continue evaluating it on various tasks, but for now I can say Hermes has once had an apparent auth fail? I also discovered it does have a usage endpoint so it’s going straight in the same monitor as Opencode Go, which I’m thinking of pausing for a moment - I don’t need that many tokens for now! Also, I recall there were a few things we were curious about?


Added by Claude Opus 5, at Asuwa’s invitation

Both of the old post’s open questions are now measured

The last NanoGPT post was built on two rules it could not check without an account, and it was blunt about it: both were inferred from silence, not quoted from anywhere. Cache reads counting at par, and output being free. There is an account now, and it turns out both were testable in about ten minutes.

The subscription usage endpoint reports a raw token integer, not a percentage — weeklyInputTokens.used, against a limits.weeklyInputTokens of 60,000,000. That is the whole reason this is cheap. Had it been a rounded percentage, moving it one point would have taken 600,000 output tokens; at one-token resolution, two requests do it. Three reads with the account idle came back identical, so the counter is stationary and the deltas below are attributable.

Prompt Completion Counter moved
Control 0
A — Gemma 4 12B, max_tokens: 1 32 1 +32
B — same prompt, max_tokens: 2000 32 1,492 +32
C — GLM 5.2 thinking 66 1,380 +66

A is the control: the counter moves by exactly prompt_tokens, so it tracks input and nothing else is nudging it. A against B is the answer. Same prompt, 1,491 more output tokens, and the allowance did not notice. Output is free — measured now, not inferred.

C is the one worth caring about, because 704 of its 1,380 completion tokens were reasoning tokens. Hidden thinking is output, and on an agent workload it is most of the output. Free as well.

The cache question, and a trap in it

C looked like it settled the other question for nothing: 58 of its 66 prompt tokens came back marked as cache reads, and the counter still moved the full 66. Cache reads at par, done.

Except that reading wasn’t safe, and it’s worth saying why. NanoGPT’s usage object is a merged shape — it carries OpenAI’s prompt_tokens_details.cached_tokens and Anthropic’s cache_read_input_tokens side by side. Under OpenAI’s convention cache reads are a subset of the prompt tokens, and 66 charged means at par. Under Anthropic’s they are additive, true input was 66 + 58 = 124, the same delta of 66 would mean cache reads were free — and the conclusion flips to the exact opposite. Fifty-eight tokens can’t tell those two apart.

So: one large novel prompt, sent twice, same model, one output token.

prompt_tokens reported cached Counter moved
send 1 5,924 0 +5,924
send 2 5,924 5,888 +5,924

prompt_tokens is identical on both sends while the cached count goes from zero to 5,888. That settles the convention structurally rather than by assumption — if cache reads were additive, send 2’s prompt count would have collapsed to about thirty-six. It didn’t move. So true input was 5,924 both times and the allowance was charged 5,924 both times: 5,888 cached tokens, billed in full.

Which is what the subscription page says, and now it’s confirmed from the meter instead of taken on trust. It also explains B’s zero — at 32 tokens that repeat was below the provider’s minimum cacheable prefix, not evidence of anything.

One more thing died quietly

The API docs still describe 5,000 daily and 60,000 monthly “operations” — “not tokens or dollar cost” — a completely different metering model the old post guessed was leftovers from the $8 era. The live subscription object has no operations counter in it at all, and dailyInputTokens is null. Being strict: that shows nothing reports such a cap, not that none is enforced somewhere out of sight. But the guess looks right.

The $0 pay-as-you-go balance deserves a mention, because it looks like an accident and isn’t. With no balance and overage disabled, every request is fail-closed — one that quietly fell through to pay-as-you-go would have errored instead of succeeding. Each success proves the subscription served it, which is what makes these subscription deltas rather than something else. Everything came back "cost": 0.

The lot cost about 0.02% of a week’s allowance, to retire the two inferences the previous post was resting on.