mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
speech: derive all model ids from sherpa catalog
This commit is contained in:
@@ -2,89 +2,21 @@ import { z } from "zod";
|
||||
|
||||
export type SherpaOnnxModelKind = "stt-online" | "stt-offline" | "tts";
|
||||
|
||||
const MODEL_IDS = {
|
||||
ZIPFORMER_BILINGUAL_ZH_EN_2023_02_20: "zipformer-bilingual-zh-en-2023-02-20",
|
||||
PARAFORMER_BILINGUAL_ZH_EN: "paraformer-bilingual-zh-en",
|
||||
PARAKEET_TDT_0_6B_V3_INT8: "parakeet-tdt-0.6b-v3-int8",
|
||||
KITTEN_NANO_EN_V0_1_FP16: "kitten-nano-en-v0_1-fp16",
|
||||
KOKORO_EN_V0_19: "kokoro-en-v0_19",
|
||||
POCKET_TTS_ONNX_INT8: "pocket-tts-onnx-int8",
|
||||
} as const;
|
||||
type DefaultModelRole = "stt" | "tts";
|
||||
|
||||
export type SherpaOnnxModelId = (typeof MODEL_IDS)[keyof typeof MODEL_IDS];
|
||||
|
||||
export const LOCAL_STT_MODEL_IDS = [
|
||||
MODEL_IDS.ZIPFORMER_BILINGUAL_ZH_EN_2023_02_20,
|
||||
MODEL_IDS.PARAFORMER_BILINGUAL_ZH_EN,
|
||||
MODEL_IDS.PARAKEET_TDT_0_6B_V3_INT8,
|
||||
] as const;
|
||||
export type LocalSttModelId = (typeof LOCAL_STT_MODEL_IDS)[number];
|
||||
|
||||
export const LOCAL_TTS_MODEL_IDS = [
|
||||
MODEL_IDS.KITTEN_NANO_EN_V0_1_FP16,
|
||||
MODEL_IDS.KOKORO_EN_V0_19,
|
||||
MODEL_IDS.POCKET_TTS_ONNX_INT8,
|
||||
] as const;
|
||||
export type LocalTtsModelId = (typeof LOCAL_TTS_MODEL_IDS)[number];
|
||||
|
||||
export const DEFAULT_LOCAL_STT_MODEL: LocalSttModelId = MODEL_IDS.PARAKEET_TDT_0_6B_V3_INT8;
|
||||
export const DEFAULT_LOCAL_TTS_MODEL: LocalTtsModelId = MODEL_IDS.POCKET_TTS_ONNX_INT8;
|
||||
|
||||
const STT_MODEL_ALIASES: Record<string, LocalSttModelId> = {
|
||||
zipformer: MODEL_IDS.ZIPFORMER_BILINGUAL_ZH_EN_2023_02_20,
|
||||
"zipformer-bilingual": MODEL_IDS.ZIPFORMER_BILINGUAL_ZH_EN_2023_02_20,
|
||||
paraformer: MODEL_IDS.PARAFORMER_BILINGUAL_ZH_EN,
|
||||
parakeet: MODEL_IDS.PARAKEET_TDT_0_6B_V3_INT8,
|
||||
"parakeet-v3": MODEL_IDS.PARAKEET_TDT_0_6B_V3_INT8,
|
||||
"parakeet-tdt": MODEL_IDS.PARAKEET_TDT_0_6B_V3_INT8,
|
||||
};
|
||||
|
||||
const TTS_MODEL_ALIASES: Record<string, LocalTtsModelId> = {
|
||||
pocket: MODEL_IDS.POCKET_TTS_ONNX_INT8,
|
||||
"pocket-tts": MODEL_IDS.POCKET_TTS_ONNX_INT8,
|
||||
kitten: MODEL_IDS.KITTEN_NANO_EN_V0_1_FP16,
|
||||
kokoro: MODEL_IDS.KOKORO_EN_V0_19,
|
||||
};
|
||||
|
||||
function createAliasedModelIdSchema<T extends readonly [string, ...string[]]>(
|
||||
values: T,
|
||||
aliases: Record<string, T[number]>
|
||||
) {
|
||||
return z.preprocess((value) => {
|
||||
if (typeof value !== "string") {
|
||||
return value;
|
||||
}
|
||||
const normalized = value.trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
return value;
|
||||
}
|
||||
return aliases[normalized] ?? normalized;
|
||||
}, z.enum(values));
|
||||
}
|
||||
|
||||
export const LocalSttModelIdSchema = createAliasedModelIdSchema(
|
||||
LOCAL_STT_MODEL_IDS,
|
||||
STT_MODEL_ALIASES
|
||||
);
|
||||
|
||||
export const LocalTtsModelIdSchema = createAliasedModelIdSchema(
|
||||
LOCAL_TTS_MODEL_IDS,
|
||||
TTS_MODEL_ALIASES
|
||||
);
|
||||
|
||||
export type SherpaOnnxModelSpec = {
|
||||
id: SherpaOnnxModelId;
|
||||
type SherpaOnnxCatalogEntry = {
|
||||
kind: SherpaOnnxModelKind;
|
||||
archiveUrl?: string;
|
||||
downloadFiles?: Array<{ url: string; relPath: string }>;
|
||||
extractedDir: string;
|
||||
requiredFiles: string[];
|
||||
description: string;
|
||||
aliases?: readonly string[];
|
||||
defaultFor?: DefaultModelRole;
|
||||
};
|
||||
|
||||
export const SHERPA_ONNX_MODEL_CATALOG: Record<SherpaOnnxModelId, SherpaOnnxModelSpec> = {
|
||||
[MODEL_IDS.ZIPFORMER_BILINGUAL_ZH_EN_2023_02_20]: {
|
||||
id: MODEL_IDS.ZIPFORMER_BILINGUAL_ZH_EN_2023_02_20,
|
||||
export const SHERPA_ONNX_MODEL_CATALOG = {
|
||||
"zipformer-bilingual-zh-en-2023-02-20": {
|
||||
kind: "stt-online",
|
||||
archiveUrl:
|
||||
"https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2",
|
||||
@@ -96,44 +28,45 @@ export const SHERPA_ONNX_MODEL_CATALOG: Record<SherpaOnnxModelId, SherpaOnnxMode
|
||||
"tokens.txt",
|
||||
],
|
||||
description: "Streaming Zipformer transducer (fast, good accuracy).",
|
||||
aliases: ["zipformer", "zipformer-bilingual"],
|
||||
},
|
||||
[MODEL_IDS.PARAFORMER_BILINGUAL_ZH_EN]: {
|
||||
id: MODEL_IDS.PARAFORMER_BILINGUAL_ZH_EN,
|
||||
"paraformer-bilingual-zh-en": {
|
||||
kind: "stt-online",
|
||||
archiveUrl:
|
||||
"https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-paraformer-bilingual-zh-en.tar.bz2",
|
||||
extractedDir: "sherpa-onnx-streaming-paraformer-bilingual-zh-en",
|
||||
requiredFiles: ["encoder.int8.onnx", "decoder.int8.onnx", "tokens.txt"],
|
||||
description: "Streaming Paraformer (often strong accuracy; heavier).",
|
||||
aliases: ["paraformer"],
|
||||
},
|
||||
[MODEL_IDS.PARAKEET_TDT_0_6B_V3_INT8]: {
|
||||
id: MODEL_IDS.PARAKEET_TDT_0_6B_V3_INT8,
|
||||
"parakeet-tdt-0.6b-v3-int8": {
|
||||
kind: "stt-offline",
|
||||
archiveUrl:
|
||||
"https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8.tar.bz2",
|
||||
extractedDir: "sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8",
|
||||
requiredFiles: ["encoder.int8.onnx", "decoder.int8.onnx", "joiner.int8.onnx", "tokens.txt"],
|
||||
description: "NVIDIA Parakeet TDT v3 (offline NeMo transducer, multilingual).",
|
||||
aliases: ["parakeet", "parakeet-v3", "parakeet-tdt"],
|
||||
defaultFor: "stt",
|
||||
},
|
||||
[MODEL_IDS.KITTEN_NANO_EN_V0_1_FP16]: {
|
||||
id: MODEL_IDS.KITTEN_NANO_EN_V0_1_FP16,
|
||||
"kitten-nano-en-v0_1-fp16": {
|
||||
kind: "tts",
|
||||
archiveUrl:
|
||||
"https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/kitten-nano-en-v0_1-fp16.tar.bz2",
|
||||
extractedDir: "kitten-nano-en-v0_1-fp16",
|
||||
requiredFiles: ["model.fp16.onnx", "voices.bin", "tokens.txt", "espeak-ng-data"],
|
||||
description: "KittenTTS (small, fast English TTS).",
|
||||
aliases: ["kitten"],
|
||||
},
|
||||
[MODEL_IDS.KOKORO_EN_V0_19]: {
|
||||
id: MODEL_IDS.KOKORO_EN_V0_19,
|
||||
"kokoro-en-v0_19": {
|
||||
kind: "tts",
|
||||
archiveUrl: "https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/kokoro-en-v0_19.tar.bz2",
|
||||
extractedDir: "kokoro-en-v0_19",
|
||||
requiredFiles: ["model.onnx", "voices.bin", "tokens.txt", "espeak-ng-data"],
|
||||
description: "Kokoro TTS (higher quality; larger).",
|
||||
aliases: ["kokoro"],
|
||||
},
|
||||
[MODEL_IDS.POCKET_TTS_ONNX_INT8]: {
|
||||
id: MODEL_IDS.POCKET_TTS_ONNX_INT8,
|
||||
"pocket-tts-onnx-int8": {
|
||||
kind: "tts",
|
||||
extractedDir: "pocket-tts-onnx-int8",
|
||||
downloadFiles: [
|
||||
@@ -176,11 +109,98 @@ export const SHERPA_ONNX_MODEL_CATALOG: Record<SherpaOnnxModelId, SherpaOnnxMode
|
||||
"reference_sample.wav",
|
||||
],
|
||||
description: "Pocket TTS ONNX (INT8) with streaming decode support (via onnxruntime).",
|
||||
aliases: ["pocket", "pocket-tts"],
|
||||
defaultFor: "tts",
|
||||
},
|
||||
} as const satisfies Record<string, SherpaOnnxCatalogEntry>;
|
||||
|
||||
export type SherpaOnnxModelId = keyof typeof SHERPA_ONNX_MODEL_CATALOG;
|
||||
|
||||
type ModelIdByKind<K extends SherpaOnnxModelKind> = {
|
||||
[Id in SherpaOnnxModelId]: (typeof SHERPA_ONNX_MODEL_CATALOG)[Id]["kind"] extends K
|
||||
? Id
|
||||
: never;
|
||||
}[SherpaOnnxModelId];
|
||||
|
||||
export type LocalSttModelId = ModelIdByKind<"stt-online"> | ModelIdByKind<"stt-offline">;
|
||||
export type LocalTtsModelId = ModelIdByKind<"tts">;
|
||||
|
||||
const ALL_MODEL_IDS = Object.keys(SHERPA_ONNX_MODEL_CATALOG) as SherpaOnnxModelId[];
|
||||
|
||||
export const LOCAL_STT_MODEL_IDS = ALL_MODEL_IDS.filter(
|
||||
(id): id is LocalSttModelId => SHERPA_ONNX_MODEL_CATALOG[id].kind !== "tts"
|
||||
);
|
||||
|
||||
export const LOCAL_TTS_MODEL_IDS = ALL_MODEL_IDS.filter(
|
||||
(id): id is LocalTtsModelId => SHERPA_ONNX_MODEL_CATALOG[id].kind === "tts"
|
||||
);
|
||||
|
||||
function resolveDefaultModelId(role: "stt"): LocalSttModelId;
|
||||
function resolveDefaultModelId(role: "tts"): LocalTtsModelId;
|
||||
function resolveDefaultModelId(role: DefaultModelRole): SherpaOnnxModelId {
|
||||
const match = ALL_MODEL_IDS.find((id) => {
|
||||
const entry: SherpaOnnxCatalogEntry = SHERPA_ONNX_MODEL_CATALOG[id];
|
||||
return entry.defaultFor === role;
|
||||
});
|
||||
if (!match) {
|
||||
throw new Error(`No default model configured for role '${role}'`);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
export const DEFAULT_LOCAL_STT_MODEL = resolveDefaultModelId("stt");
|
||||
export const DEFAULT_LOCAL_TTS_MODEL = resolveDefaultModelId("tts");
|
||||
|
||||
function buildAliasMap<T extends string>(modelIds: readonly T[]): Record<string, T> {
|
||||
const aliasMap: Record<string, T> = {};
|
||||
for (const modelId of modelIds) {
|
||||
const aliases = SHERPA_ONNX_MODEL_CATALOG[modelId as SherpaOnnxModelId].aliases ?? [];
|
||||
for (const alias of aliases) {
|
||||
aliasMap[alias.trim().toLowerCase()] = modelId;
|
||||
}
|
||||
}
|
||||
return aliasMap;
|
||||
}
|
||||
|
||||
function createAliasedModelIdSchema<T extends string>(params: {
|
||||
modelIds: readonly T[];
|
||||
aliases: Record<string, T>;
|
||||
}): z.ZodType<T> {
|
||||
const validIds = new Set(params.modelIds);
|
||||
return z.preprocess((value) => {
|
||||
if (typeof value !== "string") {
|
||||
return value;
|
||||
}
|
||||
const normalized = value.trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
return value;
|
||||
}
|
||||
return params.aliases[normalized] ?? normalized;
|
||||
}, z.string().refine((value): value is T => validIds.has(value as T))) as z.ZodType<T>;
|
||||
}
|
||||
|
||||
const STT_MODEL_ALIASES = buildAliasMap(LOCAL_STT_MODEL_IDS);
|
||||
const TTS_MODEL_ALIASES = buildAliasMap(LOCAL_TTS_MODEL_IDS);
|
||||
|
||||
export const LocalSttModelIdSchema = createAliasedModelIdSchema({
|
||||
modelIds: LOCAL_STT_MODEL_IDS,
|
||||
aliases: STT_MODEL_ALIASES,
|
||||
});
|
||||
|
||||
export const LocalTtsModelIdSchema = createAliasedModelIdSchema({
|
||||
modelIds: LOCAL_TTS_MODEL_IDS,
|
||||
aliases: TTS_MODEL_ALIASES,
|
||||
});
|
||||
|
||||
export type SherpaOnnxModelSpec = SherpaOnnxCatalogEntry & {
|
||||
id: SherpaOnnxModelId;
|
||||
};
|
||||
|
||||
export function listSherpaOnnxModels(): SherpaOnnxModelSpec[] {
|
||||
return Object.values(SHERPA_ONNX_MODEL_CATALOG);
|
||||
return ALL_MODEL_IDS.map((id) => ({
|
||||
id,
|
||||
...SHERPA_ONNX_MODEL_CATALOG[id],
|
||||
}));
|
||||
}
|
||||
|
||||
export function getSherpaOnnxModelSpec(id: SherpaOnnxModelId): SherpaOnnxModelSpec {
|
||||
@@ -188,5 +208,8 @@ export function getSherpaOnnxModelSpec(id: SherpaOnnxModelId): SherpaOnnxModelSp
|
||||
if (!spec) {
|
||||
throw new Error(`Unknown sherpa-onnx model id: ${id}`);
|
||||
}
|
||||
return spec;
|
||||
return {
|
||||
id,
|
||||
...spec,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user