Skip to content

Phase 14: registry data accuracy - #45

Merged
Phantom-VK merged 6 commits into
mainfrom
feat/rebuild-14-registry-data
Aug 26, 2026
Merged

Phantom-VK merged 6 commits into
mainfrom
feat/rebuild-14-registry-data

Conversation

@Phantom-VK

Copy link
Copy Markdown
Owner

Refreshes the model, architecture and hardware registries against primary sources, live-verified on 2026-08-26 (not copied from the phase plan's own 2026-08-22 figures, which had already drifted by the time this landed -- Gemini 2.0 Flash, one of the plan's "unchanged, correct" entries, had been shut down since 2026-06-01).

What changed

  • Single-answer fixes: DeepSeek V3's context window (128000 -> 163840, matching model_architectures.yaml and config.json), Mistral 7B standardized on v0.3 (v0.1's config.json has sliding_window: 4096, making its 32768 non-honest), H200 memory corrected to the nvidia-smi-reported 140.4 GiB, added the missing meta:llama-3-8b architecture entry (verified against two ungated mirrors since the official repo is licence-gated), corrected model_architectures.yaml's provenance claim for the three Qwen2.5 entries' max_context_length (model card's YaRN-extended figure, not config.json's native 32768).

  • Context-tiered pricing: ModelInfo gained long_context_threshold/long_context_input_price_per_million/long_context_output_price_per_million/pricing_note, all optional. costing.py picks the tier from the prompt size, not the completion size. OpenAI and Google both charge roughly double above a prompt-size threshold -- exactly the regime this app is built for; a flat rate was silently understating large documents by about half.

  • Priced roster refresh: every entry replaced with each provider's current lineup (GPT-5.6 Sol/Terra/Luna, Claude Sonnet 5 + Haiku 4.5, Gemini 3.5 Flash + 3.1 Pro Preview, DeepSeek V4 Flash), each carrying a pricing_verified_on date and a docs_url pointing at the pricing page. DeepSeek V3 is kept as its own zero-priced self-hosted entry (it's still a real open-weight model people run themselves, just no longer a hosted API product).

  • Tokenizer downloads no longer require a licence gate: all 7 previously gated repos (every meta-llama/*, both google/gemma-2-*) now point at a verified byte-identical ungated mirror. Verified without needing HF auth: the HF tree API's git blob oid for tokenizer.json isn't gate-restricted even when the file content is, so an identical oid between the official repo and its mirror proves the file is byte-identical.

  • Gemma 2's sliding-window attention is now accounted for in KV cache sizing. Both configs alternate local (4096-token window) and global attention 1:1 across layers; the old math treated every layer as full-context. At 2x the window (8192 tokens), KV cache is now exactly 75% of the old figure. On a 24GB card, the memory-bound context ceiling (past the model's own 8192 max, where KV pressure actually binds) rises from ~9,728 to ~15,616 tokens.

  • tests/test_registry_data.py: cross-consistency checks between the two YAML files, catching the exact class of drift this phase started from. It caught a real gap while being written -- the roster refresh had orphaned deepseek:deepseek-v3's architecture entry, fixed by re-adding it as a self-hosted entry.

  • docs/registry-refresh.md: the refresh procedure and sources, three paragraphs.

Test plan

  • pytest -- 269 passed, including the new test_registry_data.py
  • ruff check src/ -- clean
  • cd frontend && npm run typecheck && npm test -- clean, 110 tests passed
  • python packaging/build.py -- real build, frozen binary launches cleanly (no exceptions in the log) and stays up
  • Bridge API layer (get_models/get_architectures) serializes every new field correctly against real values
  • Every priced entry's numbers read off the provider's live page this session, pricing_verified_on records it
  • Every architecture id has a matching registry entry and vice versa (enforced by test)
  • A cost estimate above the long-context threshold uses the long-context rate (unit-tested at threshold-1/threshold/threshold+1, both Python and TS)
  • Gemma 2's fitted context on a 24GB card increased, with the real before/after numbers computed by hand, not assumed

…y and the missing Llama 3 8B architecture

Verified against live sources on 2026-08-26, not copied from the phase
doc:
- DeepSeek V3: config.json's max_position_embeddings is 163840;
  default_models.yaml said 128000, disagreeing with
  model_architectures.yaml's own 163840 for the same id.
- Mistral 7B: default_models.yaml tokenized v0.1 (config.json
  sliding_window: 4096, so its 32768 is nominal) while
  model_architectures.yaml's docs_url pointed at v0.3 (sliding_window:
  null, honestly 32768). Standardised on v0.3.
- H200: nvidia-smi reports 143771 MiB = 140.4 GiB, not the marketed
  141 GB; this file's own header already states the GiB-not-marketing
  rule for every other entry.
- meta:llama-3-8b had no architecture entry, so it silently couldn't
  appear in the Fit Check. The official repo is licence-gated (config.json
  not fetchable without an accepted licence), so verified against two
  public mirrors (NousResearch, unsloth) with identical config.json and
  matching safetensors total (8030261248).
- Corrected model_architectures.yaml's header claim that every field
  comes from config.json: the three Qwen2.5 entries' max_context_length
  is the model card's YaRN-extended figure, not config.json's native
  32768 (no rope_scaling block on any of the three).

test_architectures.py's hardcoded architecture count updated 13 -> 14.
Chose the recommended option in GUI_REBUILD/14-REGISTRY-DATA.md over the
flat-schema alternative: OpenAI and Google both now charge roughly double
above a prompt-size threshold, which is exactly the regime this app
exists for -- a flat rate would understate a 600k-token document by
about half, confidently.

ModelInfo gains long_context_threshold/long_context_input_price_per_million/
long_context_output_price_per_million/pricing_note, all optional so every
flat-priced entry is untouched. costing.py's input_cost/output_cost pick
the tier from the prompt (input) token count, not the completion size --
output_cost takes an explicit prompt_token_count for this since the two
are pried apart at every call site that has both. compare.py's call site
updated to pass it; portfolio.py's use of total_cost already threads it
through correctly.

frontend/src/lib/costing.ts mirrors the same logic (the sanctioned
core/ duplication for the Calculator's bridge-free recompute), with
boundary tests in both test_costing.py and costing.test.ts at
threshold-1/threshold/threshold+1.
… pricing

Every priced entry was live-verified against each provider's actual
pricing page on 2026-08-26 -- not copied from GUI_REBUILD/14-REGISTRY-DATA.md,
whose own reference figures (recorded 2026-08-22) had already drifted:
Gemini 2.0 Flash, which the doc called "unchanged, correct," was shut
down 2026-06-01.

- OpenAI: gpt-4o/gpt-4o-mini/gpt-4.1 replaced with the current gpt-5.6-sol/
  terra/luna lineup. Confirmed via developers.openai.com/api/docs/pricing
  and each model's own page: 1,050,000 context window, tiered pricing
  above 272,000 input tokens (2x input, 1.5x output). Tokenizer stays
  "gpt-4o" (o200k_base) -- confirmed still current for the 5.6 family.
- Anthropic: claude-3-5-sonnet/claude-3-haiku (retired) replaced with
  claude-sonnet-5 ($2/$10, 1M context) and claude-haiku-4.5 ($1/$5,
  200K context), both flat-priced -- Anthropic's own pricing page states
  the full 1M window bills at standard rates with no long-context tier.
- Google: gemini-2.0-flash/gemini-1.5-pro (both gone) replaced with
  gemini-3.5-flash (flat $1.50/$9.00) and gemini-3.1-pro-preview (tiered
  above 200,000 input tokens: $2/$12 to $4/$18), both 1,048,576 context.
- DeepSeek: deepseek-v3 (delisted) replaced with deepseek-v4-flash.
  Storing the peak/cache-miss rate ($0.44/$1.32) since this app's
  one-off analyses never hit a warm cache; off-peak halving noted via
  pricing_note. Corrected an error in the phase doc itself, which had
  the peak/off-peak hours backwards.

Added ModelInfo.pricing_verified_on (ISO date), surfaced in both the
Python dataclass and its TypeScript mirror, with a dataclass/interface
parity test that caught the TS side being out of sync.

Updated every test that referenced a now-removed model id (openai:gpt-4o,
anthropic:claude-3-5-sonnet, etc.) to the new ids; tests that construct
their own synthetic ModelInfo fixtures (test_compare.py, test_resources.py)
were unaffected since they never read the real registry file.
…licence gate

Chose Option A from GUI_REBUILD/14-REGISTRY-DATA.md: point tokenizer_name
at an ungated mirror for all 7 licence-gated repos (every meta-llama/*
entry, both google/gemma-2-*), rather than surfacing the gate in the UI.
Every self-hosted model's tokenizer now downloads with no HF token and
no licence click.

Verified identity without an HF token: the official repos' file content
isn't fetchable unauthenticated (confirmed: all 7 report gated=manual via
the HF API), but the HF tree API's git blob oid for tokenizer.json is not
gate-restricted. An identical oid between the official repo and its
mirror proves the LFS pointer -- and therefore the actual tokenizer
content it references -- is byte-identical, without downloading either
file. All 7 pairs matched:

- meta-llama/Meta-Llama-3-8B <-> NousResearch/Meta-Llama-3-8B
- meta-llama/Llama-3.1-{8B,70B,405B}-Instruct <-> NousResearch (8B, 70B) /
  unsloth (405B, as a 4-bit repo carrying the unmodified tokenizer) --
  all three share one oid, confirming one tokenizer across the family
- meta-llama/Llama-3.3-70B-Instruct <-> unsloth/Llama-3.3-70B-Instruct
- google/gemma-2-{9b,27b}-it <-> unsloth mirrors -- both official
  entries and both mirrors share one oid across the two sizes

Spot-verified 3 of the 7 mirrors with a real unauthenticated
hf_hub_download (NousResearch/Meta-Llama-3-8B, unsloth/gemma-2-9b-it,
unsloth/Llama-3.3-70B-Instruct) -- all succeeded, sizes matching the
tree API exactly.

docs_url stays on the official model page in every entry; only
tokenizer_name (what actually gets downloaded) moved to the mirror, with
a comment recording the pairing and the verification method so the
substitution isn't mysterious. resources/probe.py's existing
_GATED_HF_PREFIXES notes logic is now dead for these 7 entries specifically
(nothing in the registry starts with those prefixes anymore) but left in
place as a generic guard for probe_hf(), which takes an arbitrary repo id.
…ache sizing

Both Gemma 2 configs alternate local sliding-window (4096) and global
full attention 1:1 across layers (confirmed against config.json and
Google's own Gemma 2 writeup) -- kv_cache_bytes_per_token treated every
layer as full-context GQA, overstating KV cache by a real, measurable
amount at any context beyond the window.

kv_cache_bytes_per_token's per-token-times-context_length signature
can't express a cost that isn't linear in context length once a window
caps it. Added kv_cache_bytes(architecture, context_length, dtype)
alongside it (the clearer of the two options in the phase doc, per its
own reasoning) rather than smuggling a context dependency into a
per-token name. Both share a new _kv_cache_bytes_per_layer_per_token
helper so each rounds once, at the end, instead of compounding error by
dividing an already-rounded total by n_layers.

ModelArchitecture gains sliding_window/sliding_window_pattern (both
default 0 = full attention, so every existing entry is untouched).
selfhost.py's two call sites switched from
kv_cache_bytes_per_token(...) * context_length to kv_cache_bytes(...)
directly.

Verified by hand: at 2x the window (8192 tokens), Gemma 2 9B's KV cache
is exactly 75% of the naive all-layers-full figure (21 of 42 layers
capped to 4096 tokens each) -- a real 25% reduction, not an approximate
one. On a 24GB card, comparing current code against the pre-fix
all-layers-full math, Gemma 2 9B's memory-bound context ceiling (past
its own 8192 architectural max, where KV pressure is what actually
binds) rises from roughly 9,728 to 15,616 tokens.

New tests: Gemma 2 9B at 2x window vs at-or-under the window, a GQA
model with sliding_window=0 (every architecture before this phase)
matching its old behavior exactly, and DeepSeek V3's MLA path
unchanged.
…ation dates

tests/test_registry_data.py: pure, no network, no fixtures. Checks every
architecture id has a matching default_models.yaml entry (and vice versa
for self-hosted models), that files sharing an id agree on context
window, that every priced entry carries a docs_url and
pricing_verified_on, that pricing_verified_on parses as a real date, and
that head_dim * n_attention_heads either equals hidden_size or the entry
explains why (Gemma 2's head_dim=256 exception). No test asserts a date
is recent -- a time-bomb that reddens CI on a quiet Tuesday teaches
people to ignore CI.

This test caught a real gap the moment it was written: Task 2's roster
refresh replaced the priced deepseek:deepseek-v3 entry with
deepseek:deepseek-v4-flash, but model_architectures.yaml still has a
deepseek:deepseek-v3 entry (it's a real, separately self-hostable
open-weight model, not superseded the way its hosted-API pricing is) --
so the Fit Check would have had nothing to look up for it. Added it back
as its own zero-priced self-hosted entry, alongside the priced V4-Flash
one.

Surfaced pricing_verified_on in the Registry view as a single muted
line ("Prices verified <date>") showing the most recent verification
date across all priced entries -- not per-row, per the phase doc's own
UI guidance.

docs/registry-refresh.md: three paragraphs naming the four pricing URLs,
the config.json/safetensors-total lookup method, the gated-repo
identity-verification technique from Task 3, and the rule that
pricing_verified_on only moves when a human has actually reread the
source page that day -- including the concrete lesson from this same
phase (the reference doc's own 2026-08-22 figures had already drifted by
2026-08-26).
@Phantom-VK Phantom-VK self-assigned this Aug 26, 2026
@Phantom-VK
Phantom-VK merged commit 43a9f79 into main Aug 26, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant