Enforce strict speech providers and set parakeet local default

This commit is contained in:
Mohamed Boudra
2026-02-06 14:31:00 +07:00
parent 8889f6f05c
commit 72e2fdae2b
2 changed files with 18 additions and 41 deletions

View File

@@ -492,17 +492,13 @@ export async function createPaseoDaemon(
if ((wantsLocalDictation || wantsLocalVoiceStt || wantsLocalVoiceTts) && sherpaConfig) { if ((wantsLocalDictation || wantsLocalVoiceStt || wantsLocalVoiceTts) && sherpaConfig) {
const autoDownload = sherpaConfig.autoDownload ?? (process.env.VITEST ? false : true); const autoDownload = sherpaConfig.autoDownload ?? (process.env.VITEST ? false : true);
let sttPreset = (sherpaConfig.stt?.preset ?? "zipformer-bilingual-zh-en-2023-02-20").trim(); let sttPreset = (sherpaConfig.stt?.preset ?? "parakeet-tdt-0.6b-v3-int8").trim();
if ( if (
sttPreset !== "zipformer-bilingual-zh-en-2023-02-20" && sttPreset !== "zipformer-bilingual-zh-en-2023-02-20" &&
sttPreset !== "paraformer-bilingual-zh-en" && sttPreset !== "paraformer-bilingual-zh-en" &&
sttPreset !== "parakeet-tdt-0.6b-v3-int8" sttPreset !== "parakeet-tdt-0.6b-v3-int8"
) { ) {
logger.warn( throw new Error(`Unknown local STT preset: ${sttPreset}`);
{ sttPreset },
"Unknown Sherpa STT preset; falling back to zipformer-bilingual-zh-en-2023-02-20"
);
sttPreset = "zipformer-bilingual-zh-en-2023-02-20";
} }
let ttsPreset = (sherpaConfig.tts?.preset ?? "pocket-tts-onnx-int8").trim(); let ttsPreset = (sherpaConfig.tts?.preset ?? "pocket-tts-onnx-int8").trim();
@@ -511,11 +507,7 @@ export async function createPaseoDaemon(
ttsPreset !== "kokoro-en-v0_19" && ttsPreset !== "kokoro-en-v0_19" &&
ttsPreset !== "pocket-tts-onnx-int8" ttsPreset !== "pocket-tts-onnx-int8"
) { ) {
logger.warn( throw new Error(`Unknown local TTS preset: ${ttsPreset}`);
{ ttsPreset },
"Unknown Sherpa TTS preset; falling back to kitten-nano-en-v0_1-fp16"
);
ttsPreset = "kitten-nano-en-v0_1-fp16";
} }
const modelIds: SherpaOnnxModelId[] = []; const modelIds: SherpaOnnxModelId[] = [];
@@ -557,17 +549,13 @@ export async function createPaseoDaemon(
} }
if ((wantsLocalDictation || wantsLocalVoiceStt) && sherpaConfig) { if ((wantsLocalDictation || wantsLocalVoiceStt) && sherpaConfig) {
let preset = (sherpaConfig.stt?.preset ?? "zipformer-bilingual-zh-en-2023-02-20").trim(); let preset = (sherpaConfig.stt?.preset ?? "parakeet-tdt-0.6b-v3-int8").trim();
if ( if (
preset !== "zipformer-bilingual-zh-en-2023-02-20" && preset !== "zipformer-bilingual-zh-en-2023-02-20" &&
preset !== "paraformer-bilingual-zh-en" && preset !== "paraformer-bilingual-zh-en" &&
preset !== "parakeet-tdt-0.6b-v3-int8" preset !== "parakeet-tdt-0.6b-v3-int8"
) { ) {
logger.warn( throw new Error(`Unknown local STT preset: ${preset}`);
{ preset },
"Unknown Sherpa STT preset; falling back to zipformer-bilingual-zh-en-2023-02-20"
);
preset = "zipformer-bilingual-zh-en-2023-02-20";
} }
const base = sherpaConfig.modelsDir; const base = sherpaConfig.modelsDir;
@@ -642,11 +630,7 @@ export async function createPaseoDaemon(
preset !== "kokoro-en-v0_19" && preset !== "kokoro-en-v0_19" &&
preset !== "pocket-tts-onnx-int8" preset !== "pocket-tts-onnx-int8"
) { ) {
logger.warn( throw new Error(`Unknown local TTS preset: ${preset}`);
{ preset },
"Unknown Sherpa TTS preset; falling back to kitten-nano-en-v0_1-fp16"
);
preset = "kitten-nano-en-v0_1-fp16";
} }
try { try {
if (preset === "pocket-tts-onnx-int8") { if (preset === "pocket-tts-onnx-int8") {
@@ -714,22 +698,15 @@ export async function createPaseoDaemon(
const needsOpenAiStt = !sttService && voiceSttProvider === "openai"; const needsOpenAiStt = !sttService && voiceSttProvider === "openai";
const needsOpenAiTts = !ttsService && voiceTtsProvider === "openai"; const needsOpenAiTts = !ttsService && voiceTtsProvider === "openai";
const needsOpenAiDictation = const needsOpenAiDictation = dictationSttProvider === "openai";
dictationSttProvider === "openai" || (dictationSttProvider === "local" && !dictationSttService);
const fallbackOpenAiStt = !sttService && voiceSttProvider === "local" && Boolean(openaiSttApiKey);
const fallbackOpenAiTts = !ttsService && voiceTtsProvider === "local" && Boolean(openaiTtsApiKey);
if ( if (
(needsOpenAiStt || needsOpenAiTts || needsOpenAiDictation || fallbackOpenAiStt || fallbackOpenAiTts) && (needsOpenAiStt || needsOpenAiTts || needsOpenAiDictation) &&
(openaiSttApiKey || openaiTtsApiKey || openaiDictationApiKey) (openaiSttApiKey || openaiTtsApiKey || openaiDictationApiKey)
) { ) {
logger.info("OpenAI speech provider initialized"); logger.info("OpenAI speech provider initialized");
if (fallbackOpenAiStt) { if (needsOpenAiStt) {
logger.warn("Falling back to OpenAI STT because local STT is unavailable");
}
if (needsOpenAiStt || fallbackOpenAiStt) {
if (openaiSttApiKey) { if (openaiSttApiKey) {
const { apiKey: _sttApiKey, ...sttConfig } = config.openai?.stt ?? {}; const { apiKey: _sttApiKey, ...sttConfig } = config.openai?.stt ?? {};
sttService = new OpenAISTT( sttService = new OpenAISTT(
@@ -742,10 +719,7 @@ export async function createPaseoDaemon(
} }
} }
if (fallbackOpenAiTts) { if (needsOpenAiTts) {
logger.warn("Falling back to OpenAI TTS because local TTS is unavailable");
}
if (needsOpenAiTts || fallbackOpenAiTts) {
if (openaiTtsApiKey) { if (openaiTtsApiKey) {
const { apiKey: _ttsApiKey, ...ttsConfig } = config.openai?.tts ?? {}; const { apiKey: _ttsApiKey, ...ttsConfig } = config.openai?.tts ?? {};
ttsService = new OpenAITTS( ttsService = new OpenAITTS(
@@ -778,8 +752,8 @@ export async function createPaseoDaemon(
}), }),
}; };
} }
} else if (needsOpenAiStt || needsOpenAiTts || needsOpenAiDictation || fallbackOpenAiStt || fallbackOpenAiTts) { } else if (needsOpenAiStt || needsOpenAiTts || needsOpenAiDictation) {
logger.warn("OPENAI_API_KEY not set - OpenAI STT/TTS/dictation fallback is unavailable"); logger.warn("OPENAI_API_KEY not set - OpenAI STT/TTS/dictation is unavailable");
} }
const effectiveProviders = { const effectiveProviders = {
@@ -794,7 +768,7 @@ export async function createPaseoDaemon(
].filter((feature): feature is string => feature !== null); ].filter((feature): feature is string => feature !== null);
if (unavailableFeatures.length > 0) { if (unavailableFeatures.length > 0) {
logger.warn( logger.error(
{ {
requestedProviders: { requestedProviders: {
dictationStt: dictationSttProvider, dictationStt: dictationSttProvider,
@@ -804,7 +778,10 @@ export async function createPaseoDaemon(
effectiveProviders, effectiveProviders,
unavailableFeatures, unavailableFeatures,
}, },
"Speech provider reconciliation completed with unavailable features" "Speech provider reconciliation failed: configured features are unavailable"
);
throw new Error(
`Configured speech features unavailable: ${unavailableFeatures.join(", ")}`
); );
} else { } else {
logger.info( logger.info(

View File

@@ -220,7 +220,7 @@ export function loadConfig(
(env.PASEO_SHERPA_STT_PRESET ?? persisted.providers?.sherpaOnnx?.stt?.preset)?.trim() || (env.PASEO_SHERPA_STT_PRESET ?? persisted.providers?.sherpaOnnx?.stt?.preset)?.trim() ||
(persisted.features?.voiceMode?.stt?.preset ?? (persisted.features?.voiceMode?.stt?.preset ??
persisted.features?.dictation?.stt?.preset)?.trim() || persisted.features?.dictation?.stt?.preset)?.trim() ||
"zipformer-bilingual-zh-en-2023-02-20" "parakeet-tdt-0.6b-v3-int8"
), ),
}, },
tts: { tts: {