Model roster & benchmarks reference
Three distinct concepts share the word “model” here: the registry (what’s actually on disk), the curated catalogue (what the installer offers to download), and benchmarks (measured performance, not tied 1:1 to either).
Model registry
Section titled “Model registry”Each registered model is a Model record (hal0.registry.model), persisted as one
atomic TOML file per model under /var/lib/hal0/registry/.
| Field | Notes |
|---|---|
id, name, path |
— |
size_bytes, quant |
Derived from the GGUF header where possible, filename fallback. |
license |
— |
capabilities |
Freeform tags, normalized to a fixed modality set: chat, embed, rerank, vision, asr, tts. |
hf_repo / hf_filename |
— |
backends |
Which slot backends can run this model: GGUF → vulkan, rocm, cuda, cpu; moonshine → moonshine; kokoro → kokoro. |
mmproj |
Optional vision-projector sidecar path. |
defaults |
Tri-state launcher knobs the model now owns: context_size, extra_args, chat_template, profile, mtp, jinja, enable_thinking, vision. |
default |
Per-dispatch-type default marker. |
architecture |
e.g. llama, qwen2, gemma3, gpt-oss, qwen3next, mamba — drives MoE/context sizing. |
capability_flags.tool_calling |
Typed tri-state flag. |
Registered models split into two buckets for the dashboard UI: blessed (path under
/var/lib/hal0/models/<recipe>/<capability>/) vs pulled (anything downloaded or
hand-registered outside that layout).
Curated catalogue
Section titled “Curated catalogue”hal0.registry.curated.CuratedModel — not a file on disk, shipped in code with
the release, so a fresh install can never land on a stale pick list. This is the roster
the first-run wizard’s model cards render via GET /api/install/curated-models.
| Field | Notes |
|---|---|
id, display_name, description |
— |
family, architecture |
— |
size_gb, vram_gb_min |
— |
license, license_url |
— |
hf_repo, hf_file, mmproj_file (optional) |
— |
context_length |
— |
recommended_slot |
chat or img |
capability |
chat, embed, asr, tts, image |
tags, notes |
— |
Hardware-driven recommendation
Section titled “Hardware-driven recommendation”hardware.recommend.recommend_primary_slot(hw) is the installer’s logic for choosing
the model that seeds the primary chat slot, ordered largest-to-smallest and RAM-gated:
| Curated id | Min RAM | Class | Approx throughput |
|---|---|---|---|
Qwen3.6-35B-A3B-MTP-GGUF |
≥ 48 GB | Hybrid MoE | ~45 tok/s |
qwen3.5-9b |
≥ 16 GB | Dense | — |
qwen3-4b |
0 GB (always downloadable) | Dense | — |
llama32-3b |
CPU fallback | Dense | — |
phi3-mini |
CPU fallback | Dense | — |
Every id in this tier list must exist in the curated catalogue — enforced by test
(tests/registry/test_curation_drift.py, tests/hardware/test_recommend.py), so this
table can drift only if both source and its tests change together.
Context-window resolution for the seeded primary slot: MoE/MTP models get the full architecture-max window (their KV cache is tiny relative to a hybrid model); dense models are capped at 32768 tokens; if neither applies, the fallback is 8192.
See Hardware matrix for the backend (ROCm/Vulkan/ CUDA/CPU) selection logic this recommendation composes with.
Benchmarks
Section titled “Benchmarks”The bench/ package measures real llama.cpp performance — this is a distinct concept
from the roster above, not a per-curated-model score table.
Record schema (bench.schema) — stdlib dataclasses only, no Pydantic, so a record
is constructible with zero dependencies on the target box. Records are appended to a
JSONL file. Each record splits into:
- Identity block (feeds the dedup key
cell_key()):Model(id, gguf path, sha256, quant, size_bytes, capabilities),Engine(kind:llama-benchorllama-server, image, image digest, llama.cpp build),lane(rocm,vulkan_radv,default),Config(resolved argv/env/kv, spec block, parallel, context size),Workload(kind:pp/tg/chat/batch/embed/rerank/reuse, depth, n_prompt, n_gen, sampler, concurrency). - Environment block (
host) — deliberately excluded fromcell_key(), so a hal0 or kernel upgrade doesn’t fork the identity of an otherwise-identical measurement.
Outcome enum: ok, failed, skipped-contended, oom, hang — only ok counts as a
measured/publishable value.
Separately, [profile] sections in config/schema.py (sourced from config/seeds.py)
carry a small static per-profile tps/rtf benchmark table
(PROFILE_BENCH: dict[str, dict[str, float]]), surfaced on profile cards. This is
curated per-profile, not per-model, and is distinct from the JSONL pipeline above.
hal0 bench plan|run|status|worker|results|history|reindex|devices|publish|eval|bundle|uploadhal0 bench is a raw argparse passthrough (not a Typer sub-app) — run
hal0 bench <verb> --help for per-verb flags. Supporting modules: bench/devices.py
(device enumeration), bench/planner.py (picks what’s stale), bench/runner.py
(drives llama-bench/llama-server), bench/store.py (JSONL/db layer),
bench/publish.py (pushes results to the dashboard), bench/suites.py,
bench/regress.py.
Sharing results
Section titled “Sharing results”Benchmark results never leave the box on their own — nothing is uploaded in the background, and no verb here runs unattended. Sharing is always an explicit command you type. To share a run, package it as a self-contained bundle and attach it wherever you discuss it (forum thread, issue, chat):
hal0 bench bundle --list # see what's eligiblehal0 bench bundle --runs <run_id> --title "Strix Halo, ROCm 7" -o run.hal0bench.tar.gzA bundle contains the schema-2 records (resolved flags, engine digests,
telemetry), the profile/suite TOMLs you pass with --profile, and optional
raw artifacts (--with-artifacts). host.name is redacted by default, the
manifest carries a sha256 for every member, and the whole archive is
content-addressed — anyone can verify and reproduce what you measured.
Records with outcome: ok but no throughput measurement at all are left out
of bundles: they carry nothing to publish, and the publish API rejects a whole
upload over a single one.
Publishing to the public leaderboard
Section titled “Publishing to the public leaderboard”Maintainers of the hal0.dev leaderboard publish a bundle to the bench API, which is what backs hal0.dev/benchmarks. This requires an admin token and is not something a normal install needs:
export HAL0_BENCH_TOKEN=… # admin token; never a CLI flaghal0 bench upload run.hal0bench.tar.gzhal0 bench bundle --runs <run_id> --upload # or bundle + publish in one stepThe token is read from the environment only — passing a credential as an argv
value would expose it in ps, in shell history, and in any journald unit that
logs the command line.
Uploads are idempotent. The API is content-addressed, so re-sending a bundle that is already published is a no-op that reports the existing record count, and re-sending one that was unpublished restores it. A retry after a network failure cannot duplicate records.