Skip to content
sulimko.com

How we count

Every number on this site comes from a published source or from a formula on this page. Each formula is here twice: first in plain words, then exactly as the code computes it.

On this page

The rules behind every number

  1. 1Every number has a source and the date it was true — not the date we happened to read it.
  2. 2What a vendor claims and what someone measured are kept apart. They are shown side by side, never averaged into one number.
  3. 3When nobody has published or measured a value, you see an empty ring and the reason — never a guess.
  4. 4A formula changes only as a new version. Results computed before a change are not rewritten.

Where numbers come from

Every value carries one of five labels. Activate a dotted number by click, tap or keyboard to see its label and date.

Vendor's claim
What the vendor publishes about its own product. A claim, not a measurement.
Independent measurement
A measurement by an independent third party — a benchmark run or a public dataset — with its method and date.
Our measurement
Our own measurement on our own accounts. One person, one way of working: a case study, never ranked above an independent source.
Our calculation
A value we calculate from other values with a formula on this page, such as the price per task. It is only as fresh as its oldest input.
Lawsuit allegation
An allegation from a lawsuit. Unproven and pending — never shown as a measurement.

How fresh is fresh

Age is counted from when a fact became true, or was last confirmed — not from when we loaded it. A value past its limit is marked stale with an amber ring; a result computed from a stale value is stale too.

Kind of dataStale afterWhat it covers
Changes often14 daysPrices and limits. A price per task inherits their age.
Changes slowly45 daysBenchmark scores.
Does not ageon change onlyContext window, openness of weights — they change only with a new release.

Price per task

Price lists quote dollars per million tokens, but that is not what a job costs. A coding agent re-reads the same files again and again (cheap cached reads), writes relatively little and sometimes thinks at length.

So we price a whole typical task, from the vendor's own prices, in three kinds of work: a chat, a coding agent, and a pipeline running around the clock. The coding agent is the default everywhere on the site.

No example today: no model has both prices published.

The three kinds of work

  • Chat
    Read from cache
    20%
    Tokens in
    6000
    Tokens out
    2000
    To cache
    1000
  • Coding agent
    Read from cache
    70%
    Tokens in
    120 000
    Tokens out
    12 000
    To cache
    8000
  • 24/7 pipeline
    Read from cache
    85%
    Tokens in
    400 000
    Tokens out
    20 000
    To cache
    10 000

If a vendor publishes no price for cached reads, we price them as fresh input — no discount we cannot show.

Exactly as the code computes it
cost_per_task(model, P) =
    p_in  · T_in(P) · (1 − cache_share(P))   # fresh input
  + p_cr  · T_in(P) · cache_share(P)         # reads from cache
  + p_cw  · T_cw(P)                          # writes to cache
  + p_out · T_out_base(P) · verbosity_ratio
    # output, scaled by how much the model writes
  + p_out · T_think(model, P)                # reasoning tokens
  × geo_mult × tier_mult
    # region surcharge, peak hours, batch discount

Tokens are not the same everywhere

Models cut text into tokens differently: a newer tokenizer can produce about 30% more tokens for the same text. That is why the workloads above are defined as an amount of text and converted into each model's own tokens. Comparing prices per million tokens across vendors without this step is misleading.

Talkative models cost more

Some models write far more than others for the same task. We count that as cost: a model's output is scaled by how much it writes compared with one fixed reference model.

Writing less is cheaper, not smarter. A short answer is not a better one.

The model score, 0 to 100

Where one number helps — to sort a table — we use a score from 0 to 100 built from independent benchmarks. A part with no data is left out, never counted as zero, and an old input makes the whole score old.

  • OverallShown
    Overall = mean(Intelligence, Coding, Reasoning)only the parts a model has count
  • CodingShown
    Coding = mean(aider, SWE-bench, LiveCodeBench)today Artificial Analysis's coding index stands in, until the raw benchmarks are published
  • MathsShown
    Math = mean(MATH-500, AIME)today Artificial Analysis's maths index stands in, until the raw benchmarks are published
  • ReasoningWaiting for a source
    Reasoning = mean(GPQA, HLE)
  • SpeedShown
    Speed = percentile(median tokens/sec)among the language models whose speed was measured
  • Value for moneyShown
    Value = percentile(SCORE(Overall) / $/task coding-agent)among the models that have both a score and a price
  • LanguagesWaiting for a source
    Multilingual = mean(available multilingual signals)

Speed and value for money are a position among all models (a percentile), so they can move when new models arrive. The other parts are absolute.

How the dots read

  • Excellent80–100
  • Good60–79
  • Fair40–59
  • Weak0–39

Intelligence

Intelligence is the average over the kinds of tasks that have been measured: coding, reasoning and general knowledge. Each kind is the average of its benchmarks. A kind with no measurement is left out; a benchmark older than its limit is dropped from the number and listed as excluded.

If two sources disagree, both are shown — they are never blended into a hidden average.

Exactly as the code computes it
intelligence = mean(coding, reasoning, general)
  # only the task classes that were measured; 0–100
  coding    = mean(aider_polyglot_pct, swe_bench_verified)
  reasoning = livebench_score
  general   = intelligence_index              # Artificial Analysis

# per benchmark the latest reading counts; every reading stays in the history
# a benchmark past its freshness limit is left out of the number and listed
# the result is as fresh as the oldest benchmark that remains

Tiers: top, strong, middle, weak

Tiers use fixed borders, not a ranking among the current models, so a model keeps its tier when a new one arrives. A stale input moves a tier down, never quietly counts as fresh.

  • Intelligence, index 0–100
    Top
    ≥ 65
    Strong
    ≥ 55
    Middle
    ≥ 40
    Weak
    < 40
  • Price per coding-agent task
    Top
    ≤ $0.15
    Strong
    ≤ $0.50
    Middle
    ≤ $1.50
    Weak
    > $1.50
  • Speed, tokens per second
    Top
    ≥ 100
    Strong
    ≥ 60
    Middle
    ≥ 30
    Weak
    < 30

Speed

Speed is the median number of tokens a model writes per second, plus the wait for the first word where it has been measured. Both come from independent measurements.

How a replacement is chosen

The “find a cheaper model” answer is arithmetic, not an AI, so the same question always gets the same answer. You name your model and one wish: cheaper, faster, open weights or a longer context.

A candidate must be clearly better on that wish: at least 20% cheaper per task or 20% faster, more open weights, or a longer context window. A vendor's “0” is not a price, so such a model is never called cheaper. What it must keep is intelligence: up to 10 points below yours is the best fit, up to 20 points below a good alternative with the drop named, and further below it is not offered. A model whose intelligence nobody has measured is only worth a look. You get up to five, best verdict first; within a verdict a clearly bigger gain leads (a fresh number counts in full, an old one for less); among gains of a similar size, the smaller drop in intelligence. If none qualifies, you see the closest one and what it fell short on. For computers the same rule keeps memory instead: a box with less memory than yours, or with memory we do not know, is never offered, and “cheaper” and “faster” mean at least 20% on the box price and on the memory speed.

Exactly as the code computes it
improves ⟺ gain(candidate, yours, wish) ≥ min_step
  # price and speed: at least 20% cheaper or faster; context: a larger window;
  # weights: open > source-available > closed; a vendor's “0” is not a price
drop = intelligence(yours) − intelligence(candidate)
verdict:
  best fit          # better on every wish; drop ≤ 10 points
  good alternative  # better on every wish; drop 10–20 points, named
  worth a look      # better on some wishes only, or intelligence not measured
  not offered       # drop > 20 points; only as the closest miss
order = verdict, Σ log₂(gainᵢ) × confidenceᵢ, drop
  # best verdict first; then the bigger gain (a doubling = 1,
  # compared in half steps); then the smaller drop; at most 5
  # confidence by the age of the number: fresh 1 · aging 0.75 · stale 0.5
# an improving measure with aging or stale data is flagged on the candidate
# no candidate → the closest miss and the measure it fell short on

Computers for running agents

Machines are scored 0–100 on how well they host AI agents around the clock. Memory bandwidth weighs most, because it decides how fast several agents can write at once. A measure a machine has no data for is left out, and the other weights are rescaled — a missing price never counts as cheap.

Exactly as the code computes it
fit(machine) = 100 · Σ wᵢ · normᵢ / Σ wᵢ  # over the measures the machine has
normᵢ = (xᵢ − min) / (max − min)
  # across all machines, 0..1; price is inverted, so cheaper → 1
# weights: bandwidth 0.35 · memory 0.2 · speed 0.2
# · efficiency 0.1 · price 0.1 · cluster 0.05
# a missing measure is left out, not scored 0;
# the weights rescale over the rest

Is a coding agent still alive

We do not rank coding agents against each other — the market merges and closes them too fast. We only check their pulse: how recently the last dated release came out, capped by the project's status, so a slowing or archived agent cannot read as very alive. No dated release means an empty value, not zero.

Exactly as the code computes it
pulse(agent) = round(min(100 · recency, ceiling[status]))
# recency: 1 when the last dated release is at most 7 days old,
# 0 at 180 days or more, linear in between
# ceiling by status: active 100 · slowing 55 · discontinued 25 · archived 10
# no dated release → an empty value, never 0

Does a subscription fit how you work

For each plan we check whether your usage fits its limits. Published numeric limits come first, then an independent measurement of how much the plan really gives. A lawsuit's claim is never used. If only the vendor's claim exists, the answer is still shown, but with a wide band and the words “by the vendor's claim”. Across plans we compare one thing: what your usage would cost through the API, divided by the plan price.

Exactly as the code computes it
fit(plan | you) = tier(load)
# 1. published limits come first
  load = max(demand_5h / limit_5h, demand_week / limit_week)
# 2. otherwise an independent measurement of how much the plan gives
  load = your_$ / (measured × price)
# 3. otherwise the vendor's claimed multiplier:
# a wide band, labelled “by the vendor's claim”
# 4. nothing published → an empty answer, never a guessed fit
# fits with room at load ≤ 0.7, tight at ≤ 1, above that it won't fit

demand = prompts_per_hour × active_hours
  # prompts per active hour: chat 20 · coding agent 12
  # · pipeline 30; a burst fills a 5-hour window ×1.5
your_$ = Σ wᵢ · price_per_taskᵢ × prompts_per_month
  # what your usage would cost through the API
value  = your_$ / plan_price
  # the one number compared across plans

Our own subscription measurements

We measure what our own subscriptions give: every session is priced at public API rates, and the last 30 days are divided by the monthly plan price. That is a different base from a vendor's “usage per session” claim, so the two are never compared as one number. It is one person's way of working and cannot be reproduced independently — a case study. Only totals are published; the content of sessions never leaves our machine.

How the news feed is ordered

The feed is ordered by a fixed rule, not by taste: the kind of change, times how big it is, times whether you can act on it. People earn a place by what they ship — dated work of their own — not by followers; an account with a big audience and no output is flagged. Every price story shows the model's price per task, the same number as in the catalog.

Exactly as the code computes it
relevance(story) = round(weight[kind] · size · actionable · 100)
# weight by kind of change, see the table below; an unknown kind → 0.5
# size: how big the change is, 0..1
# (a parsed price move; unknown → 0.5, never 0)
# actionable: a model you can call 0.7
# · a known model outside the catalog 0.5 · anything else 0.4

# a person qualifies ⟺ at least one dated piece of their own work:
# commits, releases, posts
# flagged: followers with no work, or followers ÷ works ≥ 50 000
# a follower count never qualifies anyone

Weight by kind of change

  • Pricesa price drop 1 · a price rise 0.85
  • Limits and plan termsa plan gives less than promised 0.95 · a limit tightened 0.9 · how usage is counted changed 0.9 · what a plan covers changed 0.85 · a plan withdrawn 0.85 · a limit loosened 0.8 · a plan gives more 0.8 · which tools a plan works with changed 0.8 · a new plan 0.75
  • New models and resultsbeats the model it is compared with 0.95 · a new model or product 0.75 · a new benchmark result 0.65
  • Statusreleased, deprecated or shut down 0.7
  • What users reporta wave of complaints 0.6 · complaints died down 0.45

How complete the data is

A model counts as fully described when it has a context window, both prices and a status. The share is read live from the registry; a low number is a real gap, shown as is.

  • Models you can call100% fully described · 142 models
  • Models available through a router28.6% fully described · 497 models
  • Every model row, including benchmark-only18.7% fully described · 761 models

Across all 761 rows: context window 65.3% · both prices 18.7% · status 100%.

619 models have benchmark scores but no price or context. They appear in ratings and benchmarks, not in the catalog.

Context windows: 338 taken from public catalogs, 159 carried over from the base model of the same family.

264 rows have no context window from any public source.