Model registry and HF census#
Step 5 of the port (Porting map): which Hugging Face models this engine can run, kept current every day. Two numbers are reported, and they are never added together:
- Mapped: a backend's own code accepts the model's architecture.
- Checked: a model of that architecture loaded, answered and streamed through
1bit serveon Strix Halo (tests/serve_e2e.sh).
The registry#
registry/architectures.json maps each HF architecture (a config's architectures[0],
such as Qwen3ForCausalLM) to its GGUF architecture and the backends that accept it.
tools/registry_build.py generates it from the pinned sources. None of it is typed in by
hand:
| Backend | Accepts the architecture when |
|---|---|
| HF -> GGUF | a @ModelBase.register(...) class in our HRX fork's llama.cpp converter names it |
hrx |
the GGUF architecture is in our HRX fork's src/llama-arch.cpp; the same llama-server runs it on the CPU (--device cpu), so hrx also means the CPU route |
npu |
the NPU engine's model type: qwen3 (its kernels are built for Qwen3-0.6B's shapes) |
The vulkan column (the upstream llama.cpp release the engine built for Vulkan) left with that
build in RFC #213 stage 3. With it went the HF class names only the upstream
converter registers: 33 classes, 23 of them for architectures the HRX fork does not run (among
them zamba, zamba2, blackmamba; qwen4exp is back since pin e57beb97) and 10 aliases of architectures it does run
(DFlash drafters, exaone-moe, nemotron_h_moe), which a GGUF converted elsewhere still runs on.
The zinc column (ZINC's parseArchitecture; 63 HF architectures on 2026-10-03) left with ZINC in
the core strip (2026-10-04).
On 2026-10-04 (core strip): 290 HF architectures mapped, hrx 290, npu 7. The file
also lists gguf_architectures.hrx, every GGUF architecture the pinned fork's runtime builds (141
then): CMakeLists.txt compiles that list into 1bit serve, which refuses any other architecture on
hrx and cpu with a pointer to Lemonade's llamacpp backend. Mapped means a backend's code accepts the architecture; the census below reports how many were checked. registry/architectures.json always holds the current counts and the pins they come from: every pin bump regenerates it (scripts/registry-regen.sh, run by the bump workflows), and CI's registry_pins test fails a pin that moved without it.
Reviewed gaps. Some unmapped architectures only look like a supported family. Architecture gaps records why each of them is not an alias. registry/significant.json lists those classes, and tools/registry_build.py --check-gaps (ctest registry_gaps) fails if one becomes mapped without a recorded reason.
Checked models#
tools/registry_check.py <1bit> --models <dir> runs tests/serve_e2e.sh for every row of
registry/check_models.tsv and records the result in registry/checked.json, failures
included. The architecture recorded is the one the backend loads: the GGUF
general.architecture, or the NPU directory's model_type. Checked on Strix Halo
2026-09-25, engine 8c2805d (hrx rows at the llama.cpp pin 96f6b89):
| GGUF architecture | Model | hrx | npu |
|---|---|---|---|
qwen3 |
Qwen3-0.6B | pass | pass |
qwen2 |
Qwen2.5-7B-Instruct | pass | |
qwen3moe |
Qwen3-Coder-30B-A3B | pass | |
qwen35moe |
Qwen3.6-35B-A3B Q8_0 | pass | |
deepseek2 |
GLM-4.7-Flash | pass | |
minicpm |
MiniCPM4-8B | pass | |
llama |
MiniCPM5-1B | pass |
(The vulkan rows, which passed on the same date, were dropped from registry/check_models.tsv and
registry/checked.json with the Vulkan build, as were the Zyphra Zamba rows, which ran on Vulkan
only. The zinc rows went with ZINC in the core strip.)
GLM-4.7-Flash and Qwen3-Coder-30B-A3B failed on HRX until the llama.cpp pin 96f6b89 (#95).
The pin fixes four things:
- HRX0 now claims flash attention for MLA heads (576) and at full context (262144).
- The path without flash attention now compiles.
- HRX0 no longer claims a sigmoid MoE router.
- HRX0's expert matmul (MUL_MAT_ID) now reads each token's expert ids at their real row
stride. It used to read them packed, so every token of a batched prompt after the first
went to the wrong experts. Qwen MoE models were immune, because their router dispatch
supplies the stride.
The census#
tools/census.py walks every page of the HF API's text-generation listing (with each
model's config inline) and counts models by architecture. registry/census.json keeps the
counts and the coverage read against the registry and the checked results. The
census.yml workflow runs daily at 05:17 UTC. It rebuilds the registry from the pins,
sweeps HF, and opens a PR when anything changed.
The census of 2026-10-17 (the first full sweep ran 2026-09-25), with registry/census.json holding the latest:
| models | share of those with an architecture | |
|---|---|---|
| Text-generation models on HF | 425,483 | |
| With an architecture in their config | 338,650 (2,822 architectures) | |
| Mapped | 320,418 | 94.62% |
| Checked | 216,406 | 63.9% |
| Backend | Mapped | Checked |
|---|---|---|
| hrx | 94.62% | 63.9% |
| npu | 53.77% | 9.37% |
"Checked" counts every model whose architecture has a passing model. It does not mean each
of those models was run. The unmapped architectures with the most models are
Step1MoEForCausalLM (2,882), ParlerTTSForConditionalGeneration (1,585),
ChessForCausalLM (970) and LlavaLlamaForCausalLM (453); OPTForCausalLM and
GPTNeoForCausalLM, which led this list in September, are mapped now.
tools/census.py --pr-body lists the top ten.
The watch#
The sweep is a snapshot, so a class that appears tomorrow moves the mapped share
quietly. tools/census_watch.py polls the newest text-generation models (createdAt
descending), reads each one's architecture class from the config inline in the listing,
and compares it against registry/architectures.json — the same read census.py's
coverage() makes, so "uncovered" here means "not in the number the census reports". No
per-model fetch and no compiled probe: the registry is generated data, keyed by the HF
architecture class the census counts.
Exit 0 means every newest model is mapped; exit 1 is the alert — a class arrived that
no backend accepts. One kind of unmapped class is reported without the alert: a class whose
models all load through custom modeling code (auto_map in the config, or a runtime that is
not Transformers, so Transformers has no implementation of it either) and that fewer than 3
uploaders publish. Research one-offs like that arrive every day (Ihatetomatoes/nanoBeard-sloop-14M
is a raw pytorch nanoGPT checkpoint whose config says architectures: ["GPT"] and
model_type: nanobeard-gpt, engine#296). It alerts once 3 uploaders use it, and a reviewed
class (registry/significant.json) always alerts, unless its entry says "watch": "report":
a research architecture reviewed as not an alias that nothing upstream implements
(GrugMoeForCausalLM, engine#381). The watcher lists those as . REVIEWED without the alert.
The watch runs daily at 04:30 UTC (ahead of the 05:17 sweep) in two places:
- GitHub Actions (.github/workflows/census-watch.yml, RFC #246), which files one deduped
census-watch issue. Only its alert job holds issues: write, and that job runs no
repository code.
- the systemd timer on the development box (scripts/1bit-census-watch.{service,timer}, from
the ~/census-main worktree that tracks origin/main), which marks its unit failed and
logs every run to ~/.1bit/logs/census-watch-*.log.
A class the watcher flags is one of two things, and the run says which:
- new class — map it in
registry/architectures.json, but only when a pinned backend's code really accepts the architecture (rule 3 in CONTRIBUTING.md: recognized is not verified). - reviewed, not an alias — already in
registry/significant.json(Architecture gaps); it needs real engine support, and if a backend starts accepting it, the reason is recorded asmapped_ok.
Gated repos (no config without a token) are reported as unverifiable and never fail the run; derivatives (a quantized GGUF, a LoRA adapter) have no config by design and are skipped, because the release they derive from carries the config and is what gets checked.
Commands#
tools/registry_build.py # rebuild registry/architectures.json from the pins
tools/registry_build.py --check # exit 1 if it is stale
tools/registry_check.py build/1bit --models ~/models # run the checks on Strix Halo
tools/census.py # full HF sweep (about 420 pages)
tools/census.py --report # recompute coverage from the saved counts
tools/census_watch.py # newest models vs the registry; exit 1 on an uncovered class
scripts/census-watch.sh # the same, with the log file and the origin/main refresh