mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-17 18:25:42 +02:00
[eric] voice: small.en-q5_1 is the accuracy-first default, bundled base serves while it downloads in background
This commit is contained in:
@@ -19,16 +19,17 @@ const crypto = require('crypto');
|
||||
const MODELS = [
|
||||
{ id: 'tiny.en-q5_1', file: 'ggml-tiny.en-q5_1.bin', label: 'Tiny', note: 'Fastest, but gets lost past ~15s of speech', bytes: 32166155, sha256: 'c77c5766f1cef09b6b7d47f21b546cbddd4157886b3b5d6d4f709e91e66c7c2b' },
|
||||
{ id: 'base.en-q5_1', file: 'ggml-base.en-q5_1.bin', label: 'Base (compact)', note: 'Base quality and speed, 90MB less to download and hold', bytes: 59721011, sha256: '4baf70dd0d7c4247ba2b81fafd9c01005ac77c2f9ef064e00dcf195d0e2fdd2f' },
|
||||
{ id: 'base.en', file: 'ggml-base.en.bin', label: 'Base', note: 'Balanced, the default', bytes: 147964211, sha256: 'a03779c86df3323075f5e796cb2ce5029f00ec8869eee3fdfb897afe36c6d002' },
|
||||
{ id: 'small.en-q5_1', file: 'ggml-small.en-q5_1.bin', label: 'Small', note: 'Steadier on accents and noise, ~2.7x slower', bytes: 190098681, sha256: 'bfdff4894dcb76bbf647d56263ea2a96645423f1669176f4844a1bf8e478ad30' },
|
||||
{ id: 'base.en', file: 'ggml-base.en.bin', label: 'Base', note: 'Fast and light; the instant fallback while Small downloads', bytes: 147964211, sha256: 'a03779c86df3323075f5e796cb2ce5029f00ec8869eee3fdfb897afe36c6d002' },
|
||||
{ id: 'small.en-q5_1', file: 'ggml-small.en-q5_1.bin', label: 'Small', note: 'Most accurate, the default; steadier on accents and noise', bytes: 190098681, sha256: 'bfdff4894dcb76bbf647d56263ea2a96645423f1669176f4844a1bf8e478ad30' },
|
||||
];
|
||||
// Measured on an M2 (quiet machine, 3.5s/8.1s/26.4s utterances, median of 5):
|
||||
// tiny 174/154/241ms base-q5_1 212/414/656ms base 208/398/734ms small 865/1108/1869ms
|
||||
// base.en stays the default: quantizing it saves download and RAM but buys no speed on Metal, and
|
||||
// small costs 2.7x the latency. large-v3-turbo is deliberately absent, it measured both slowest and
|
||||
// least accurate here (4.1s on a 3.5s clip, and it fell apart on the long one).
|
||||
// small.en-q5_1 is the default (Eric's call, 2026-08-05: accuracy first): streaming partials hide
|
||||
// most of its extra decode cost, and the bundled base.en serves instantly while it downloads.
|
||||
// large-v3-turbo is deliberately absent, it measured both slowest and least accurate here
|
||||
// (4.1s on a 3.5s clip, and it fell apart on the long one).
|
||||
|
||||
const DEFAULT_MODEL_ID = 'base.en';
|
||||
const DEFAULT_MODEL_ID = 'small.en-q5_1';
|
||||
const BASE_URL = 'https://huggingface.co/ggerganov/whisper.cpp/resolve/main/';
|
||||
|
||||
function modelById(id) {
|
||||
|
||||
@@ -194,6 +194,14 @@ async function p_bootServer(resourceDir, userDataDir) {
|
||||
// settled-rejected promise forever so every later call kept throwing "model-downloading" even after
|
||||
// the model finished. Clearing on rejection here lets the next call retry cleanly.
|
||||
async function ensureServer(resourceDir, userDataDir) {
|
||||
// The accuracy-first default may not be on disk yet: pull it in the background while the bundled
|
||||
// fallback serves this dictation; the model-switch check below hot-swaps once it lands. Only runs
|
||||
// when the user actually dictates, so an idle install never silently downloads 190MB.
|
||||
if (!whisperModels.isInstalled(userDataDir, selectedModelId)
|
||||
&& !(process.env.OPENSWARM_WHISPER_MODEL && fs.existsSync(process.env.OPENSWARM_WHISPER_MODEL))
|
||||
&& !whisperModels.downloadStatus().downloading) {
|
||||
whisperModels.downloadModel(userDataDir, selectedModelId);
|
||||
}
|
||||
// A warm server is only reusable if it holds the file we would load now: a model switch, or the
|
||||
// user's pick finishing its download while a fallback was serving, has to re-boot.
|
||||
if (proc && port && resolveModel(resourceDir, userDataDir) !== loadedModelFile) stopServer();
|
||||
|
||||
Reference in New Issue
Block a user