feat(startup): pre-warm default Whisper model at launch in background thread

This commit is contained in:
2026-04-18 09:28:03 +01:00
parent 8c1bec98ca
commit ddcf93649c
2 changed files with 42 additions and 1 deletions

View File

@@ -72,7 +72,7 @@ fn model_capability(
} }
} }
fn load_model_from_disk(model_id: &ModelId) -> Result<Box<dyn kon_transcription::SpeechModel + Send>, String> { pub fn load_model_from_disk(model_id: &ModelId) -> Result<Box<dyn kon_transcription::SpeechModel + Send>, String> {
let entry = model_registry::find_model(model_id) let entry = model_registry::find_model(model_id)
.ok_or_else(|| format!("Unknown model: {model_id}"))?; .ok_or_else(|| format!("Unknown model: {model_id}"))?;
@@ -155,6 +155,42 @@ pub async fn ensure_model_loaded(
Ok(()) Ok(())
} }
/// Spawns a background task that loads the default Whisper model into memory
/// if it is already downloaded. Returns immediately — errors are logged, never panicked.
///
/// Call this once from app setup() after AppState is managed.
pub fn prewarm_default_model(whisper_engine: Arc<LocalEngine>) {
let model_id = default_model_id_for_engine("whisper");
if !model_manager::is_downloaded(&model_id) {
return;
}
if whisper_engine
.loaded_model_id()
.as_ref()
.map(|id| id == &model_id)
.unwrap_or(false)
{
return;
}
tokio::spawn(async move {
let result = tokio::task::spawn_blocking(move || {
load_model_from_disk(&model_id).map(|model| {
whisper_engine.load(model, model_id);
})
})
.await;
match result {
Ok(Ok(())) => eprintln!("[startup] Whisper model pre-warmed successfully"),
Ok(Err(e)) => eprintln!("[startup] Whisper pre-warm failed: {e}"),
Err(e) => eprintln!("[startup] Whisper pre-warm task panicked: {e}"),
}
});
}
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RuntimeCapabilities { pub struct RuntimeCapabilities {

View File

@@ -215,6 +215,11 @@ pub fn run() {
db, db,
}); });
{
let whisper = app.state::<AppState>().whisper_engine.clone();
crate::commands::models::prewarm_default_model(whisper);
}
if let Err(e) = tray::setup(app) { if let Err(e) = tray::setup(app) {
eprintln!("Failed to setup tray: {e}"); eprintln!("Failed to setup tray: {e}");
} }