LLMModel Museum

Model Catalog Architecture

This repository is an append-only historical catalog of facts claimed by model publishers. It describes models, not individual deployments. A serving provider may expose a smaller context window or a different capability set; those deployment constraints are outside this registry.

Catalog scope

A publisher repository is not automatically a model this registry collects. Two independent questions decide what enters the catalog: who published it and what kind of model it is.

Publishers. providers/*.yaml is the reviewed publisher catalog and the definition of the core. A brand-new record is only added when its publisher resolves to a reviewed provider file; a discovery from an unlisted long-tail publisher (community fine-tunes, mirror directories) is skipped instead. Existing long-tail records are kept as historical facts and are still enriched, but the unattended feeds no longer extend them. Adding a publisher file is the explicit way to widen the scope: the tool never invents official URLs on its own.

A reviewed provider file names the publisher's official organizations and, for publishers that ship weights, enables discovery of that organization. Its aliases list records the variant developer spellings a publisher has shipped under, such as bytedance for ByteDance Seed or stepfun-ai for StepFun, so the same publisher is not split into two catalog entries. Publishers that only serve a closed API keep strategy: aggregator, which leaves OpenRouter as the authoritative identity source for them. A publisher with an official organization declares strategy: publisher and require_corroboration: true, which holds an OpenRouter-only record as a candidate until the publisher's own repository, identifier or official link confirms it: the catalog then carries first-party models and an official model card URL instead of an aggregation artifact.

Models. The catalog collects callable models that a Go application can route to:

It does not collect:

Scope is decided from the publisher's own metadata — repository tags, declared architecture, identifiers and (only for unambiguous wording) the description — not from the upstream pipeline tag alone. A publisher tag such as text-generation describes a tensor signature, not a product category, which is how protein checkpoints originally reached this catalog.

internal/registry/scope.go implements the decision and task catalog-doctor reports every affected record with its reason. A record can overrule the classifier with an explicit kind field, and the automatic intake policy in cmd/catalogsync is deliberately narrower than the catalog scope: ranking, speech and translation models are collected when a human adds them, but the daily sweep does not walk an organization's entire speech and translation back catalogue.

Trust model

Facts are selected in this order:

  1. reviewed human-maintained YAML;
  2. the publisher's structured API or official documentation;
  3. a repository owned by the publisher's configured Hugging Face or ModelScope organization;
  4. OpenRouter structured metadata;
  5. evidence-backed AI suggestions, only after explicit review.

OpenRouter remains the broad default discovery feed. It is not the canonical owner of model names or publisher specifications. Existing model YAML is never removed merely because an upstream feed stops listing it.

OpenRouter serving variants are not model identities. Suffixes such as :batch, :free, and :thinking are folded into the underlying model and retained as runtime aliases plus identifiers.openrouter values. Named modes such as -pro or -fast are folded only when the upstream description explicitly says they use the same underlying model or have identical capabilities; independently published models such as o3-pro remain separate.

Two further classes of upstream records are provider or inference packaging rather than model identities, so they are never compiled into models_gen.go or the public catalog:

The classification lives in internal/registry/variant.go, and catalog scope in internal/registry/scope.go. A record can make the decision explicit with the optional kind field:

kind: model            # model | serving-artifact | draft-head | adapter | out-of-scope | quantization

An explicit kind always wins over the ID and description patterns, so a reviewed record can override a false positive. serving-artifact, draft-head, adapter, quantization and out-of-scope are excluded from every compiled artifact; an empty kind means model. The generator, the public catalog, Hugging Face candidate materialization and the Codex exporter all use IsCompiledKind, so an excluded kind can never reach models_gen.go, catalog.json or a runnable Codex entry.

Publisher catalog

providers/*.yaml defines canonical publisher names, official entry points and organizations that may be queried deterministically. A Hugging Face repository is treated as official only when its organization is explicitly configured in the corresponding publisher file.

Each publisher may declare who owns its model identity:

identity:
  strategy: publisher             # publisher | aggregator (default)
  canonical_prefix: deepseek      # optional stable ID prefix
  require_corroboration: true     # optional; holds new discoveries as candidates

publisher means the provider's official API or organization repositories are authoritative and OpenRouter is only a discovery and fallback feed. It requires at least one authoritative source (organizations.huggingface, organizations.modelscope, or official.api). aggregator is the default and means OpenRouter is authoritative because the provider has no first-party machine-readable source.

require_corroboration is opt-in and only valid together with publisher. When set, a brand-new record discovered through OpenRouter is written as lifecycle: candidate until an official organization repository or official link confirms it, and task catalog-promote will not activate it before then. Candidate records still appear on the public catalog page, so a genuinely published model is never hidden; only its compiled identity waits for a first-party source. Publishers that also ship closed models leave the flag off because they have no repository to corroborate against.

The catalog intentionally starts with major publishers. task catalog-audit lists long-tail publisher strings that still need a reviewed provider record; the tool never invents official URLs. task catalog-doctor writes a read-only data/catalog-doctor.json listing every record by kind plus routing aliases, draft heads, quantization variants with their format, out-of-scope records with their reason, pretrained -base variants, resolved identity sources, records whose identity is not yet corroborated, and publisher models that still lack an organization repository.

Model records

models/**/*.yaml remains the human-readable source of truth. New optional fields separate model identity and evidence from discovery metadata:

developer: qwen
links:
  official: https://qwen.ai/...
  model_card: https://huggingface.co/Qwen/...
identifiers:
  official: [Qwen3-32B]
  huggingface: [Qwen/Qwen3-32B]
  openrouter: [qwen/qwen3-32b]
provenance:
  context_length:
    source: official_model_card
    url: https://huggingface.co/Qwen/...

Top-level fields remain convenient compiled values. provenance explains why a value was selected without turning each value into a deeply nested object. It is audit metadata, not permission to overwrite the value: once a top-level field exists in YAML, every automatic source treats it as immutable.

A model may also pin where its identity came from. This is the highest-priority override and is only needed when the automatic resolution is wrong or when a closed model must be accepted without a first-party repository:

identity:
  source: manual        # manual | official | official_huggingface | official_modelscope | openrouter
  verified: true

When the block is absent, internal/identity resolves the origin in this order: an explicit block, then a repository inside one of the publisher's declared official organizations, then an official identifier or link (official_* or official), and finally OpenRouter. OpenRouter is authoritative for aggregator publishers and is reported unverified for publisher-strategy publishers until a first-party source corroborates it. Publishers that declare an official organization use publisher strategy; the five without one (Anthropic, OpenAI, OpenRouter, Perplexity, xAI) keep the aggregator default. Corroboration gating is enabled for the 13 publishers whose releases are effectively open-weight: allenai, arcee-ai, cohere, deepseek, ibm-granite, microsoft, minimax, moonshotai, nousresearch, nvidia, tencent, thinkingmachines and zai. Publishers that also ship closed API models (Amazon, ByteDance Seed, Google, Meta, Mistral, Qwen) leave require_corroboration off until a first-party source for closed models exists, because they have no repository to corroborate against.

First-party identity APIs

Publishers without open weights get their first-party source from an official model-list API. The shape is declarative because vendors differ in authentication and payload:

identity:
  strategy: publisher
  require_corroboration: true
  official_api:
    url: https://api.anthropic.com/v1/models
    env: ANTHROPIC_API_KEY      # absent value => that publisher is skipped
    auth: x-api-key             # bearer | x-api-key | query | none
    headers:
      anthropic-version: "2023-06-01"
    items_path: data            # response field holding the array
    id_field: id                # id | name
    id_prefix: models/          # stripped from every identifier (Gemini)
    link_template: ""           # optional {id} template for an official link

OpenAI, Anthropic, Google and xAI are configured this way. task official-identity queries them and records only the official identifier (and an official link when a template is configured) in identifiers.official and links.official; it never overwrites attributes. It is a dry run unless -- -apply is passed, it writes data/official-identity.json, and a publisher whose key is unset is reported as skipped_no_credentials instead of failing, so it is safe to run without secrets.

Matching is exact on a normalized identifier, with a single local key allowed to prefix a longer official identifier (which covers dated ids such as claude-sonnet-4-5-20250929). Ambiguous matches are reported and never guessed. A dated or versioned release is a model of its own: the 2505 and 2512 builds of one family are separate records, and qwen-vl-max is not the older Qwen-VL. Only an exact identity, a declared repository or a corroborating link folds two ids into one model, while a precision variant never does. Because these publishers now have a first-party source, they enable require_corroboration: a model discovered by OpenRouter stays a candidate until its official API or an official link confirms it, while remaining visible on the public catalog page.

Incremental workflow

OpenRouter discovery ─┐
                     ├─> compare with historical YAML -> enrich -> AI suggestions -> review
official HF orgs ────┘
                                                        -> generate artifacts

The initial historical backfill uses the same commands with reviewed allowlists. This makes the one-time work resumable and ensures subsequent GitHub Actions runs exercise exactly the same path on a much smaller delta.

Generation is deterministic: network acquisition happens once, and final Go code generation reads the immutable cache without another upstream request. CI checks both models_gen.go and the local audit report for drift. Context and maximum-output corrections are release-worthy model facts.