--- name: Core model registry type: architecture-map-page slice: 05-core-storage-hotkey-build last_verified: 2026/05/09 --- # Core model registry > **Where you are:** [Architecture map](../README.md) → [Core, Storage, Hotkey, Build](README.md) → Core model registry **Plain English summary.** The static catalogue of every speech-to-text model Lumotia ships or knows how to download. One Parakeet ONNX model and six Whisper GGML variants, each with pinned Hugging Face revisions and SHA256 digests so a downloaded file can be verified bit-for-bit against the registry. Pure data — the recommendation scoring lives in [`core-recommendation.md`](core-recommendation.md). ## At a glance - File: `crates/core/src/model_registry.rs` (247 LOC). - External deps: standard library only (`LazyLock`). - Public surface: `Engine`, `SpeedTier`, `AccuracyTier`, `LanguageSupport`, `ModelFile`, `ModelEntry`, `all_models`, `find_model`. - Consumers: slice 2 model commands, the model manager, the recommendation engine ([`core-recommendation.md`](core-recommendation.md)), the runtime-capabilities banner, the frontend model picker. ## What's in here ### Enums — `crates/core/src/model_registry.rs:7-36` ```rust pub enum Engine { Whisper, Parakeet, Moonshine } pub enum SpeedTier { Instant, Fast, Moderate, Slow } pub enum AccuracyTier { Excellent, Great, Good } pub enum LanguageSupport { EnglishOnly, Multilingual(u16) } ``` `Moonshine` is reserved (no live entries today). `LanguageSupport::Multilingual(u16)` carries the count of supported languages but only the variant is used in scoring. ### `ModelFile` — `crates/core/src/model_registry.rs:39` ```rust pub struct ModelFile { pub filename: &'static str, pub url: &'static str, pub size: Megabytes, pub sha256: &'static str, // hex, length 64 } ``` Every URL pins a specific Hugging Face revision SHA. The registry's test (`model_registry.rs:222-246`) asserts that no URL contains `/resolve/main/` and that every digest is exactly 64 hex characters. ### `ModelEntry` — `crates/core/src/model_registry.rs:50` ```rust pub struct ModelEntry { pub id: ModelId, pub engine: Engine, pub display_name: &'static str, pub disk_size: Megabytes, pub ram_required: Megabytes, pub speed_tier: SpeedTier, pub accuracy_tier: AccuracyTier, pub languages: LanguageSupport, pub files: Vec, pub description: &'static str, } ``` ### `ALL_MODELS` — `crates/core/src/model_registry.rs:63` A `LazyLock>`. Seven entries: | ID | Engine | Disk | RAM | Speed | Accuracy | Notes | |---|---|---|---|---|---|---| | `parakeet-ctc-0.6b-int8` | Parakeet | 650 MB | 700 MB | Instant | Great | Four ONNX shards. English only. | | `whisper-tiny-en` | Whisper | 75 MB | 390 MB | Fast | Good | Bundled with the app. | | `whisper-base-en` | Whisper | 142 MB | 500 MB | Fast | Good | Sweet spot for low-RAM. | | `whisper-small-en` | Whisper | 466 MB | 1024 MB | Moderate | Great | Accuracy-first. | | `whisper-distil-small-en` | Whisper | 336 MB | 900 MB | Fast | Great | Distilled, ~6× faster than `small`. | | `whisper-medium-en` | Whisper | 1500 MB | 2600 MB | Slow | Excellent | Best Whisper accuracy. | | `whisper-distil-large-v3` | Whisper | 1550 MB | 2800 MB | Moderate | Excellent | Near `large-v3` accuracy. | All entries are English-only at present. Multilingual variants would slot into `languages` cleanly. ### Public functions ```rust pub fn all_models() -> &'static [ModelEntry]; // model_registry.rs:208 pub fn find_model(id: &ModelId) -> Option<&'static ModelEntry>; // model_registry.rs:213 ``` Both return references into the `LazyLock`. No allocation. ## Data flow / contract - Pure data. Lookups are read-only. - The Parakeet entry's four files are fetched by the model downloader as a directory of `/` siblings (see [`core-paths.md`](core-paths.md)). Whisper entries are single GGML files. - The `description` field is user-facing copy. British-English spelling enforced. - SHA256 verification happens in the model downloader (slice 3), not here. ## Tests `crates/core/src/model_registry.rs:217-246`: - `every_model_file_has_sha256_and_pinned_url` — guard against accidental drift. SHA must be 64 hex chars; URL must not contain `/resolve/main/`. ## Watch-outs - **Hugging Face revisions can be force-pushed.** The pinned revision SHAs in the URLs are content addresses on HF's git LFS, but a maintainer with admin rights can in theory rewrite history. The local SHA256 verification at download time catches this. There is no automated CI check that re-fetches and verifies; verification happens lazily on user-facing downloads. - **`description` is `&'static str`.** No i18n. If we localise the model picker we will need a key plus a separate string table. - **Adding a new model requires a recompile.** No runtime registry override path. Conscious choice — keeps the surface area small and the SHA256 invariants meaningful. - **`Moonshine` is in the enum but no entries.** Compiler does not complain because the enum is `non_exhaustive`-shaped via match arms inside scoring (see [`core-recommendation.md`](core-recommendation.md)). When a Moonshine entry lands, the scoring path needs an explicit accelerator branch. ## See also - [Public types and enums (Megabytes, ModelId)](core-types-and-enums.md) - [Recommendation scoring](core-recommendation.md) - [App paths (`speech_model_dir`)](core-paths.md) - [Slice 3 model manager](../03-audio-transcription/README.md)