Add Danish fine-tune catalog entries under a single pending Hugging Face owner constant

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Lucas Winther
2026-10-29 22:00:33 +01:00
co-authored by Claude Opus 5.5
parent f8ce3120fe
commit 2a4f5b16a5
3 changed files with 120 additions and 1 deletions
+16
View File
@@ -1224,3 +1224,19 @@ whole-file output is equally bad, which is exactly what the absolute bar
exists to catch.
**Consequence:** full `bun test` ≈ 19 min on CPU (en_alien ≈ 20 min of it
on a cold run); the fast suite excludes this file.
## D-WS6a — Danish fine-tuned Whisper models: our own ONNX + CTranslate2 conversions, unpublished until the owner says go
**Status:** Proposed (2026-10-29, spec 001 Goal 6)
**Candidates checked (licence + architecture, from each repo's model card, config and notices):**
- `thorhojhus/whisper-small-danish` — MIT; plain `WhisperForConditionalGeneration`, whisper-small
shapes and tokenizer unchanged (80 mel bins, 12/12 layers, vocab 51865). **Kept.**
- `thorhojhus/whisper-large-v3-turbo-danish` — MIT; plain large-v3-turbo (128 mel, 32/4 layers,
vocab 51866). **Kept.**
- `danish-foundation-models/edda-v0.2` — **Apache-2.0 confirmed** (licensor: the Alexandra
Institute; base model MIT); plain large-v3-turbo architecture, so Transformers.js loads it like the
stock turbo. Its `generation_config.json` pins `language: "da"`, `task: "transcribe"` and
`num_beams: 5`. **Kept.**
**Catalog:** three entries with `verified: false` everywhere, ids built from one exported constant
`DANISH_MODELS_HF_OWNER` (placeholder `"PENDING-OWNER"`): `<owner>/<name>-ONNX` for the browser
engine and `<owner>/<name>-ct2-int8` as `fasterWhisperModel` (a Hub repo id — faster-whisper accepts
those as well as its aliases). Publishing under the owner's account is a one-line change.
+52
View File
@@ -164,6 +164,27 @@ const ACCEL_Q4: DtypeDefault = {
note: "q4: the medium fp16 conversions fail to load / overflow (D-022).",
};
// ---------------------------------------------------------------------------
// Danish fine-tunes (D-WS6a)
// ---------------------------------------------------------------------------
/**
* Hugging Face account that hosts our conversions of the Danish Whisper
* fine-tunes (D-WS6a). Both the ONNX repos (browser engine) and the
* CTranslate2 int8 repos (server engine) hang off this one value, so
* publishing under the owner's account is a one-line change here. Until the
* owner confirms the account and the repos exist, it stays a placeholder.
*/
export const DANISH_MODELS_HF_OWNER = "PENDING-OWNER";
/** Catalog id + matching faster-whisper repo for one published conversion. */
function danishRepos(name: string): Pick<WhisperModel, "id" | "fasterWhisperModel"> {
return {
id: `${DANISH_MODELS_HF_OWNER}/${name}-ONNX`,
fasterWhisperModel: `${DANISH_MODELS_HF_OWNER}/${name}-ct2-int8`,
};
}
// ---------------------------------------------------------------------------
// The catalog (D-006: curated, not exhaustive)
// ---------------------------------------------------------------------------
@@ -259,6 +280,37 @@ export const MODELS: readonly WhisperModel[] = [
decoderParamsM: 174,
defaults: { wasm: WASM_Q4, webgpu: WEBGPU_FP16_Q4, webnn: WEBNN_FP16 },
},
// Danish fine-tunes (D-WS6a): unchanged Whisper architectures, so the
// parameter counts are their base models'. Conversions by us, weights by
// the original authors (credited in each published repo's model card).
{
// thorhojhus/whisper-small-danish (MIT), fine-tune of whisper-small.
...danishRepos("whisper-small-danish"),
displayName: "Whisper Small (Danish)",
multilingual: true,
encoderParamsM: 88,
decoderParamsM: 156,
defaults: { wasm: WASM_Q8, webgpu: WEBGPU_FP16_Q4, webnn: WEBNN_FP16 },
},
{
// thorhojhus/whisper-large-v3-turbo-danish (MIT).
...danishRepos("whisper-large-v3-turbo-danish"),
displayName: "Whisper Large v3 Turbo (Danish)",
multilingual: true,
encoderParamsM: 635,
decoderParamsM: 174,
defaults: { wasm: WASM_Q4, webgpu: WEBGPU_FP16_Q4, webnn: WEBNN_FP16 },
},
{
// danish-foundation-models/edda-v0.2 (Apache-2.0, Alexandra Institute),
// fine-tune of whisper-large-v3-turbo.
...danishRepos("edda-v0.2"),
displayName: "Edda v0.2 (Danish)",
multilingual: true,
encoderParamsM: 635,
decoderParamsM: 174,
defaults: { wasm: WASM_Q4, webgpu: WEBGPU_FP16_Q4, webnn: WEBNN_FP16 },
},
];
export function getModel(id: string): WhisperModel | undefined {
+52 -1
View File
@@ -1,5 +1,6 @@
import { describe, test, expect } from "bun:test";
import {
DANISH_MODELS_HF_OWNER,
DEFAULT_MODEL_ID,
MODELS,
WHISPER_LANGUAGES,
@@ -32,6 +33,9 @@ describe("MODELS catalog", () => {
"onnx-community/whisper-medium.en_timestamped",
"onnx-community/whisper-medium-ONNX",
"onnx-community/whisper-large-v3-turbo",
`${DANISH_MODELS_HF_OWNER}/whisper-small-danish-ONNX`,
`${DANISH_MODELS_HF_OWNER}/whisper-large-v3-turbo-danish-ONNX`,
`${DANISH_MODELS_HF_OWNER}/edda-v0.2-ONNX`,
]);
expect(new Set(ids).size).toBe(ids.length);
});
@@ -70,7 +74,9 @@ describe("MODELS catalog", () => {
});
test("every model maps to a faster-whisper name for the server engine (D-013)", () => {
for (const model of MODELS) {
// The Danish conversions (D-WS6a) have no faster-whisper alias; their
// server-engine name is a Hub repo id — covered by the Danish suite below.
for (const model of MODELS.filter((m) => !m.id.startsWith(`${DANISH_MODELS_HF_OWNER}/`))) {
// The onnx-community ids and faster-whisper's aliases share the same
// size suffix ("tiny.en", …, "large-v3-turbo") once repo-name
// decorations ("_timestamped", "-ONNX") are stripped; keeping them
@@ -86,6 +92,51 @@ describe("MODELS catalog", () => {
});
});
describe("Danish fine-tune conversions (D-WS6a)", () => {
const owner = `${DANISH_MODELS_HF_OWNER}/`;
const danish = MODELS.filter((model) => model.id.startsWith(owner));
test("are published under one owner constant, still a placeholder until the owner confirms", () => {
expect(DANISH_MODELS_HF_OWNER).toBe("PENDING-OWNER");
expect(danish.map((model) => model.id)).toEqual([
`${owner}whisper-small-danish-ONNX`,
`${owner}whisper-large-v3-turbo-danish-ONNX`,
`${owner}edda-v0.2-ONNX`,
]);
});
test("point the server engine at the matching CTranslate2 int8 conversion under the same owner", () => {
for (const model of danish) {
const ct2 = model.id.replace(/-ONNX$/, "-ct2-int8");
expect(model.fasterWhisperModel).toBe(ct2);
expect(getFasterWhisperModel(model.id)).toBe(ct2);
}
});
test("are multilingual (language/task are sent) and unverified on every device", () => {
for (const model of danish) {
expect(model.multilingual).toBe(true);
for (const device of ["wasm", "webgpu", "webnn"] as const) {
expect(model.defaults[device].verified).toBe(false);
}
}
});
test("share their base model's parameter counts (unchanged architecture)", () => {
const small = getModel("onnx-community/whisper-small")!;
const turbo = getModel("onnx-community/whisper-large-v3-turbo")!;
const [smallDa, turboDa, edda] = danish;
for (const [model, base] of [
[smallDa!, small],
[turboDa!, turbo],
[edda!, turbo],
] as const) {
expect(model.encoderParamsM).toBe(base.encoderParamsM);
expect(model.decoderParamsM).toBe(base.decoderParamsM);
}
});
});
describe("resolveDefaultDtype", () => {
test("WASM defaults: q8 for small models, q4 for large ones", () => {
expect(resolveDefaultDtype("onnx-community/whisper-tiny.en", "wasm")).toBe("q8");