feat(kon): add core crate — types, traits, hardware, model registry, recommendation
- Value objects: ModelId, EngineName, Megabytes, AudioSamples, Segment, Transcript - KonError enum with thiserror - Constants centralised: audio pipeline, VAD, RAM thresholds, inference threading - SpeechToText and TextProcessor provider traits with ProviderRegistry - Unified model registry (Whisper tiny/base/small/medium + Parakeet CTC int8) - Hardware detection: probe_ram, probe_cpu, probe_gpu (stub), probe_os - Recommendation engine: score_model (pure function), rank_recommendations (sorted) - 5 tests passing, clippy clean Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
166
crates/core/src/model_registry.rs
Normal file
166
crates/core/src/model_registry.rs
Normal file
@@ -0,0 +1,166 @@
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use crate::types::{Megabytes, ModelId};
|
||||
|
||||
/// Which inference backend a model uses.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Engine {
|
||||
Whisper,
|
||||
Parakeet,
|
||||
Moonshine,
|
||||
}
|
||||
|
||||
/// Qualitative speed classification.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SpeedTier {
|
||||
Instant,
|
||||
Fast,
|
||||
Moderate,
|
||||
Slow,
|
||||
}
|
||||
|
||||
/// Qualitative accuracy classification.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum AccuracyTier {
|
||||
Excellent,
|
||||
Great,
|
||||
Good,
|
||||
}
|
||||
|
||||
/// Language support scope.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum LanguageSupport {
|
||||
EnglishOnly,
|
||||
Multilingual(u16),
|
||||
}
|
||||
|
||||
/// File required for a model download.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModelFile {
|
||||
pub filename: &'static str,
|
||||
pub url: &'static str,
|
||||
pub size: Megabytes,
|
||||
}
|
||||
|
||||
/// All metadata for a single downloadable model.
|
||||
/// This is pure data — no scoring logic lives here.
|
||||
#[derive(Debug, Clone)]
|
||||
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<ModelFile>,
|
||||
pub description: &'static str,
|
||||
}
|
||||
|
||||
static ALL_MODELS: LazyLock<Vec<ModelEntry>> = LazyLock::new(|| {
|
||||
vec![
|
||||
ModelEntry {
|
||||
id: ModelId::new("parakeet-ctc-0.6b-int8"),
|
||||
engine: Engine::Parakeet,
|
||||
display_name: "Parakeet CTC 0.6B (int8)",
|
||||
disk_size: Megabytes(613),
|
||||
ram_required: Megabytes(600),
|
||||
speed_tier: SpeedTier::Instant,
|
||||
accuracy_tier: AccuracyTier::Great,
|
||||
languages: LanguageSupport::EnglishOnly,
|
||||
files: vec![
|
||||
ModelFile {
|
||||
filename: "model_int8.onnx",
|
||||
url: "https://huggingface.co/onnx-community/parakeet-ctc-0.6b-ONNX/resolve/main/onnx/model_int8.onnx",
|
||||
size: Megabytes(1),
|
||||
},
|
||||
ModelFile {
|
||||
filename: "model_int8.onnx_data",
|
||||
url: "https://huggingface.co/onnx-community/parakeet-ctc-0.6b-ONNX/resolve/main/onnx/model_int8.onnx_data",
|
||||
size: Megabytes(611),
|
||||
},
|
||||
ModelFile {
|
||||
filename: "tokenizer.json",
|
||||
url: "https://huggingface.co/onnx-community/parakeet-ctc-0.6b-ONNX/resolve/main/tokenizer.json",
|
||||
size: Megabytes(1),
|
||||
},
|
||||
],
|
||||
description: "Fastest local model — near-instant transcription",
|
||||
},
|
||||
ModelEntry {
|
||||
id: ModelId::new("whisper-tiny-en"),
|
||||
engine: Engine::Whisper,
|
||||
display_name: "Whisper Tiny (English)",
|
||||
disk_size: Megabytes(75),
|
||||
ram_required: Megabytes(390),
|
||||
speed_tier: SpeedTier::Fast,
|
||||
accuracy_tier: AccuracyTier::Good,
|
||||
languages: LanguageSupport::EnglishOnly,
|
||||
files: vec![ModelFile {
|
||||
filename: "ggml-tiny.en.bin",
|
||||
url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en.bin",
|
||||
size: Megabytes(75),
|
||||
}],
|
||||
description: "Bundled with app — works instantly",
|
||||
},
|
||||
ModelEntry {
|
||||
id: ModelId::new("whisper-base-en"),
|
||||
engine: Engine::Whisper,
|
||||
display_name: "Whisper Base (English)",
|
||||
disk_size: Megabytes(142),
|
||||
ram_required: Megabytes(500),
|
||||
speed_tier: SpeedTier::Fast,
|
||||
accuracy_tier: AccuracyTier::Good,
|
||||
languages: LanguageSupport::EnglishOnly,
|
||||
files: vec![ModelFile {
|
||||
filename: "ggml-base.en.bin",
|
||||
url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en.bin",
|
||||
size: Megabytes(142),
|
||||
}],
|
||||
description: "Good balance of speed and accuracy",
|
||||
},
|
||||
ModelEntry {
|
||||
id: ModelId::new("whisper-small-en"),
|
||||
engine: Engine::Whisper,
|
||||
display_name: "Whisper Small (English)",
|
||||
disk_size: Megabytes(466),
|
||||
ram_required: Megabytes(1024),
|
||||
speed_tier: SpeedTier::Moderate,
|
||||
accuracy_tier: AccuracyTier::Great,
|
||||
languages: LanguageSupport::EnglishOnly,
|
||||
files: vec![ModelFile {
|
||||
filename: "ggml-small.en.bin",
|
||||
url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.en.bin",
|
||||
size: Megabytes(466),
|
||||
}],
|
||||
description: "Accuracy-first English transcription",
|
||||
},
|
||||
ModelEntry {
|
||||
id: ModelId::new("whisper-medium-en"),
|
||||
engine: Engine::Whisper,
|
||||
display_name: "Whisper Medium (English)",
|
||||
disk_size: Megabytes(1500),
|
||||
ram_required: Megabytes(2600),
|
||||
speed_tier: SpeedTier::Slow,
|
||||
accuracy_tier: AccuracyTier::Excellent,
|
||||
languages: LanguageSupport::EnglishOnly,
|
||||
files: vec![ModelFile {
|
||||
filename: "ggml-medium.en.bin",
|
||||
url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.en.bin",
|
||||
size: Megabytes(1500),
|
||||
}],
|
||||
description: "Best Whisper accuracy — needs 4+ GB RAM",
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
/// Returns all known models. Pure data, no scoring.
|
||||
pub fn all_models() -> &'static [ModelEntry] {
|
||||
&ALL_MODELS
|
||||
}
|
||||
|
||||
/// Find a model by its ID.
|
||||
pub fn find_model(id: &ModelId) -> Option<&'static ModelEntry> {
|
||||
ALL_MODELS.iter().find(|m| &m.id == id)
|
||||
}
|
||||
Reference in New Issue
Block a user