Instructions to use ahdrage/norwegian-parakeet with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use ahdrage/norwegian-parakeet with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("automatic-speech-recognition", model="ahdrage/norwegian-parakeet")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("ahdrage/norwegian-parakeet", device_map="auto") - Notebooks
- Google Colab
- Kaggle
norwegian-parakeet
Norwegian (Bokmål) speech-to-text: moondream/parakeet-ultra (a post-trained NVIDIA Parakeet TDT 0.6B v3) fine-tuned only on speech with open licences, about 1,770 hours of unique audio. Every source, its licence and where it came from is listed in docs/DATA.md. The model writes cased, punctuated text and decodes greedily, with no language model.
Code, training recipe and data preparation: https://github.com/ahdrage/norwegian-parakeet (Apache-2.0). Weights: CC BY 4.0.
It is a sibling of norsk-asr and uses its text normalization and scoring, so numbers are scored the same way.
Results
WER (%) with norsk-asr's normalize() (lowercase, no punctuation) on the full test sets, greedy decoding, over all utterances including those with digits.
| Test set | Clips | Hours | WER | CER |
|---|---|---|---|---|
| Tuva (3 held-out speakers) | 482 | 0.5 | 3.1 | 0.9 |
| NST validation | 1,500 | 2.7 | 4.2 | 1.2 |
| NPSC test | 5,518 | 11.0 | 6.1 | 2.2 |
| FLEURS Norwegian test | 357 | 1.3 | 7.4 | 2.3 |
| Stortinget validation | 697 | 5.0 | 11.7 | 6.8 |
| NorGovPCC (held-out) | 1,157 | 8.0 | 12.5 | 6.9 |
| NB Samtale (spontaneous conversation, held-out speakers) | 4,137 | 8.2 | 17.7 | 8.8 |
Some caveats on reading these:
- The reference text is not always what was said. Stortinget and NorGovPCC transcripts are edited (hesitations and some small words are left out), so a model that hears them correctly is still scored as wrong. This sets a floor on those sets.
- Tuva is small (0.5 h, 3 speakers), so its number moves a lot between runs.
- NorGovPCC's test split was not filtered; the training split was.
- The model is evaluated on clips of up to 30 s. Longer recordings need to be cut first; this has not been tested here.
Where the errors are
On NB Samtale most of the remaining errors are in casual speech: dialect forms ("korsen" heard as "hvordan"), "også" heard as "og så", dropped small words and laughter marked as "heh" in the reference. On FLEURS they are mostly foreign names and loanwords and reference spellings (fram/frem, "i følge" / "ifølge"). Both sets contain speech that is rare in the training data.
Each pass
The model is trained in four passes, each continuing from the last at a lower learning rate. WER (%):
| Test set | Pass 1 | Pass 2 | Pass 3 | Pass 4 (final) |
|---|---|---|---|---|
| Tuva | 3.2 | 3.1 | 3.1 | 3.1 |
| NST | 4.6 | 4.2 | 4.2 | 4.2 |
| NPSC | 7.3 | 6.3 | 6.2 | 6.1 |
| FLEURS | 8.1 | 7.9 | 7.8 | 7.4 |
| Stortinget | 12.0 | 11.8 | 11.7 | 11.7 |
| NorGovPCC | 13.0 | 12.6 | 12.5 | 12.5 |
| NB Samtale | 19.3 | 18.1 | 17.8 | 17.7 |
Passes 1–3 were scored on the first 5,000 NPSC clips; pass 4 on all 5,518.
Things that were tried on top of this and gave no gain (so are not in the final model): averaging the
weights of passes 1–3, rescoring n-best lists with a word trigram model trained on the training
transcripts, and speed and noise augmentation in pass 4 (--wav-aug, still in train.py).
Usage
import torch
from transformers import AutoProcessor, ParakeetForTDT
processor = AutoProcessor.from_pretrained("ahdrage/norwegian-parakeet")
model = ParakeetForTDT.from_pretrained("ahdrage/norwegian-parakeet").eval()
# audio: 16 kHz mono float32 numpy array, up to ~30 s per clip
inputs = processor(audio, sampling_rate=16000, return_tensors="pt")
with torch.no_grad():
out = model.generate(**inputs)
print(processor.batch_decode(out.sequences, skip_special_tokens=True)[0])
How it is trained
- Targets: the original transcripts, cased and punctuated (NPSC's
<ee>-style markers removed), since that is what Parakeet writes. Scoring normalizes both sides. - Passes (
scripts/run_open.sh, mixes inscripts/mix.py): pass 1 is one epoch over everything at LR 5e-5; pass 2 goes at 1.5e-5 and repeats the smaller, cleaner sources (NPSC, NorGovPCC, Tuva ×2, NB Samtale ×2) against a quarter of Stortinget; pass 3 at 5e-6 does the same with half of NST and an eighth of Stortinget; pass 4 at 3e-6 is a short pass weighted towards conversational speech (NB Samtale ×4, FLEURS ×3). - Everything trains: all 0.6B parameters, AdamW, cosine decay with 500 warm-up steps, 64 s of audio per batch, bf16 autocast. BatchNorm keeps its pretrained statistics and layer-drop is off: with small batches, batch statistics blew the loss up from ~5 to ~3,000. No SpecAugment.
- Digit boundaries: the tokenizer loses the word boundary before a word that starts with a digit, which
glues numbers to the previous word.
encode_targetsintrain.pyadds the boundary token explicitly. - Filtering: clips over 30 s, and clips whose transcripts cannot fit their audio (over 30 or under 2
characters per second), are left out. NorGovPCC and Tuva clips are also checked against a reference model
(CER ≤ 0.3, or 0.4 for clips with digits, and at most one of the first or last three words unheard). Tuva's
speakers read punctuation aloud ("komma", "punktum", "nytt avsnitt"); those words are cut out using the
reference model's word times, so the model does not learn dictation commands. See
src/norsk_parakeet/clean_pack.py. - Memory-lean TDT loss (
src/norsk_parakeet/loss.py). transformers' TDT loss materializes the joint output (frames × tokens × 8,193) in float32 several times and runs out of memory on a 24 GB card at useful batch sizes. The loss here computes the joint in time chunks under activation checkpointing and keeps only what the recursion needs: blank, next-label and duration log-probs. The backward pass uses alpha–beta posteriors instead of autograd through the recursion, and on the GPU both recursions are Triton kernels (src/norsk_parakeet/tdt_triton.py), one program per utterance walking all anti-diagonals. For a batch of two 30 s clips that is 1.8 ms against 2.2 s for the PyTorch loop.tests/test_loss.pychecks the gradients against autograd and the kernels against the PyTorch recursion. - Resumable: a checkpoint (weights, optimizer, batch position) every 30 minutes, written atomically (about 7 GB each); a restart with the same command continues with the same batch order.
Hardware: one RTX PRO 4000 Blackwell (24 GB), shared with other jobs. The four passes took about 35 hours together.
Reproducing
See the GitHub repository for the data preparation, mixes and training commands.
Licences and attribution
Code: Apache-2.0. The weights are CC BY 4.0, as the base model is (NVIDIA's parakeet-tdt-0.6b-v3, via moondream/parakeet-ultra), with attribution to NVIDIA and Moondream. Training data attribution:
- Stortinget speech and transcripts (the National Library of Norway's Stortinget subset)
- NST, NPSC, NB Samtale: National Library of Norway, Språkbanken (CC0)
- NorGovPCC: National Library of Norway, NLOD 2.0
- Tuva Speech Database: National Library of Norway, created by Max Manus AS, CC BY 4.0
- FLEURS: Google, CC BY 4.0
Details, links and checksums are in docs/DATA.md. Two points are not settled and should be read before relying on the model commercially:
- NST is distributed by the National Library as CC0, but the Hugging Face mirror used here carries no licence tag.
- Stortinget: the subset carries a CC0 tag on its mirror. Stortinget's own terms for its recordings were being updated in June 2026, and whether they reach the audio in this subset is unresolved.
This is not legal advice and no lawyer has reviewed it.
- Downloads last month
- 35
Model tree for ahdrage/norwegian-parakeet
Base model
moondream/parakeet-ultra