Loading…
Loading…
Private beta model from the NB-ASR project at the National Library of Norway. This is a Norwegian-focused adaptation of the Qwen3-ASR-0.6B family, with reading-optimised and verbatim output, Bokmål/Nynorsk written targets, and Norwegian-speech-to-English translation. It also learns from long recordings, sparse-speech recordings, contextual vocabulary and intentionally empty targets.
This is an experimental checkpoint for authorised evaluation and integration, not a production guarantee. Model weights do not include access rights to the underlying speech datasets. The repository is private, not public-and-gated.
| Input | Requested output | Control |
|---|---|---|
| Norwegian speech | Reading-optimised Bokmål | target_lang="nob", style="reading_optimised" |
| Norwegian speech | Verbatim Bokmål | target_lang="nob", style="verbatim" |
| Norwegian speech | Written Nynorsk | target_lang="nno", either style |
| Norwegian speech | English translation | target_lang="eng", either style |
| Audio plus relevant vocabulary | The same task, with optional keyword context | keywords="metoprolol Tromsø Nordlandssykehuset" |
Nynorsk and English training targets generally reuse Norwegian source audio; these are output-language controls, not evidence of an independently trained English-speech corpus. The original model's other languages have not been systematically revalidated after this adaptation.
Verbatim aims to retain spoken repetitions, repairs and hesitations. It does
not guarantee exact reproduction of every disfluency. Reading-optimised output
aims at readable written text; it is not summarisation. There is no hard-coded
rule to cap repetitions at three. Neither <summary> nor the reserved
<reading_optimised> token was used as a training style in this run.
Use a fresh Python 3.12 environment with a suitable CUDA-enabled GPU. The
release examples target qwen-asr==0.0.6 / Transformers 4.57.6. That package's
vLLM extra pins vLLM 0.14.0; use a compatible CUDA/PyTorch environment rather than
upgrading individual components independently.
python -m pip install "qwen-asr==0.0.6" huggingface_hub soundfile scipy
hf auth login
hf download NbAiLab/nb-asr-bokfink02-beta --local-dir ./nb-asr-bokfink02-beta
cd nb-asr-bokfink02-beta
Your HF account/token must have read access to this private repository. Do not
put tokens in source files, notebooks, shared logs or command-line examples.
For reproducible deployment, download a fixed Hub commit with --revision;
the model's release provenance is included in release_provenance.json.
The accompanying inference.py is a small, optional local helper. Read it before
running it. It does not install custom model implementations or require
trust_remote_code=True; Qwen classes come from the installed qwen-asr package.
Always load the tokenizer, processor and chat_template.jinja from this
repository. The custom tokenizer remaps reserved slots without changing the
embedding dimensions. Do not substitute the original Qwen tokenizer or one from
another NB-ASR release.
| Control | Where it belongs | Exact content |
|---|---|---|
| Contextual keywords | SYSTEM message | Plain space-separated vocabulary, or "" |
| Output style | USER text, after the audio | "" for reading; "\n<verbatim>" for verbatim |
| Output language | Fixed ASSISTANT generation prefix | One of the headers below |
| Target code | Assistant prefix |
|---|---|
nob |
language Norwegian<asr_text> |
nno |
language Norwegian Nynorsk<asr_text> |
eng |
language English<asr_text> |
The conceptual serialisation for keyword-conditioned verbatim Bokmål is:
<|im_start|>system
metoprolol Tromsø Nordlandssykehuset<|im_end|>
<|im_start|>user
<|audio_start|><|audio_pad|><|audio_end|>
<verbatim><|im_end|>
<|im_start|>assistant
language Norwegian<asr_text>
Use the processor to create this prefix; do not hand-tokenise the audio markers.
The generated continuation is the transcript only. Leave SYSTEM empty when
no keywords are needed. Do not place <verbatim> in the system message or put
nob, nno, eng into the user message as instructions. Do not substitute
Norwegian Bokmål for the trained Norwegian header.
The upstream Qwen3ASRModel.transcribe(language=...) validates against its
original language list, which does not contain our Norwegian selectors. Also,
its context parameter supplies SYSTEM text: context="<verbatim>" is wrong
for this checkpoint. The helper uses explicit processor prompts and the ordinary
Transformers/vLLM generation backends, avoiding both pitfalls without globally
patching the upstream library.
Supply a short list of plausible names/terms, joined by spaces, preserving
multiword phrases. No Vocabulary: prefix, comma-separated list, true/distractor
labels or instructions are needed. For example:
metoprolol Eliquis Tromsø Nordlandssykehuset
Keywords are hints, not text that must be inserted. Most training rows had no keywords: 96.05% empty SYSTEM context; 2.24% true-plus-distractor context; 1.12% distractors only; 0.59% true keywords only. The contextual feature has not been separately benchmarked for this beta release. Prefer ordinary no-context ASR unless useful vocabulary is actually available.
The following commands use the downloaded helper and local checkpoint:
# Reading-optimised Bokmål
python inference.py /path/to/audio.wav --model . --target-lang nob
# Verbatim Bokmål
python inference.py /path/to/audio.wav --model . --target-lang nob --style verbatim
# Written Nynorsk
python inference.py /path/to/audio.wav --model . --target-lang nno --style verbatim
# English translation of Norwegian speech
python inference.py /path/to/audio.wav --model . --target-lang eng
# Verbatim with optional keyword context
python inference.py /path/to/audio.wav --model . --style verbatim \
--keywords "metoprolol Eliquis Tromsø Nordlandssykehuset"
Output is JSON containing text, target_lang, style, duration_seconds,
truncated and optional timestamps. The helper downmixes to mono and resamples
to 16 kHz without normalising away quiet voices or applying VAD. It uses BF16,
greedy decoding and explicitly enables the generation KV cache; this overrides
the checkpoint's training-time use_cache=false setting without changing weights.
For Python integration, run from the downloaded directory:
from inference import BokfinkASR
model = BokfinkASR(model=".", backend="transformers", device="cuda:0")
result = model.transcribe(
"/path/to/audio.wav",
target_lang="nob",
style="verbatim",
keywords="", # SYSTEM vocabulary; not the style tag
)
print(result["text"])
Install the supported vLLM extra in a suitable environment:
python -m pip install "qwen-asr[vllm]==0.0.6"
CUDA_VISIBLE_DEVICES=0 python inference.py /path/to/audio.wav \
--model . --backend vllm --target-lang nob --style verbatim \
--gpu-memory-utilization 0.60 --max-model-len 32768 --max-new-tokens 4096
For reading-optimised output, omit --style verbatim. Nynorsk, English and
keywords use exactly the same switches as the Transformers example.
Programmatic vLLM entry points must use the multiprocessing main guard:
from inference import BokfinkASR
if __name__ == "__main__":
model = BokfinkASR(
model=".", backend="vllm", gpu_memory_utilization=0.60,
max_model_len=32768, max_new_tokens=4096,
)
print(model.transcribe("/path/to/audio.wav", target_lang="nob", style="verbatim"))
This is offline vLLM inference with the same explicit prompt contract, not an
OpenAI-compatible HTTP server. The helper constructs requests with rendered
prompt and multi_modal_data={"audio": [waveform]}. For a separate serving
integration, preserve all three controls above: generic transcription APIs or
chat templates that omit the assistant-language prefix can change the task.
The example limits concurrent sequences to one to give a conservative starting point for long audio. Tune batch/concurrency and memory utilisation on your own hardware; no universal minimum VRAM or throughput claim is made here.
Use the Norwegian-adapted companion
NbAiLab/nb-asr-beta-qwen06b-08052026-forced-aligner.
The helper pins its revision to 6ddd1268709255a14f576b4db898942eb24b8e38.
It is a separate model, not part of the ASR weights. The aligner runs through
Transformers even when ASR runs through vLLM; reserve GPU memory for both, or
place them on separate devices. Separate HF access may be required for it.
For a short recording:
CUDA_VISIBLE_DEVICES=0 python inference.py /path/to/audio.wav \
--model . --backend vllm --target-lang nob --style verbatim \
--gpu-memory-utilization 0.60 --timestamps
Or in Python:
from inference import BokfinkASR
if __name__ == "__main__":
model = BokfinkASR(model=".", backend="vllm", gpu_memory_utilization=0.60)
model.load_aligner(device="cuda:0")
result = model.transcribe("/path/to/audio.wav", style="verbatim", timestamps=True)
print(result["text"])
for word in result["timestamps"]:
print(word["text"], word["start"], word["end"])
For ASR on GPU 0 and alignment on GPU 1, expose both GPUs, set
CUDA_VISIBLE_DEVICES=0,1, and use --aligner-device cuda:1. vLLM uses its
normal visible-device selection; the example uses one tensor-parallel ASR GPU.
The same alignment API works with backend="transformers".
Important alignment boundaries:
Training includes short clips and long/sparse-speech examples up to 1,200 s (20 minutes). This is the supported input ceiling of the preparation/example path, not a guarantee of accurate 20-minute transcription. The small natural long-form evaluation cohort is much shorter than 20 minutes; long recordings need independent testing. Streaming behaviour has not been validated for this release helper.
The helper rejects audio over 1,200 s rather than cropping it. It disables
processor truncation and defaults to 4,096 generated tokens. Dense long speech
may require a larger token limit and context budget. If generation reaches the
limit, it warns and returns truncated=true; do not mistake this for a complete
transcript. Check memory and quality when increasing limits.
This model was trained fresh from the custom-tokenizer Qwen base, not from the earlier Lunde 100k, longfix or hesitation-boost checkpoints. Those model cards informed these user instructions; their post-training results do not transfer to this release.
| Setting | Value |
|---|---|
| Architecture family | Qwen3-ASR-0.6B |
| Initial model | NbAiLab/Qwen3-ASR-0.6B-custom-tokenizer |
| Initial revision | b8c29a95eed5271e057ce61b5ba4afb178c426a6 |
| Fine-tuning | Full parameter, BF16 |
| Hardware | 64 GPUs across 16 Olivia nodes |
| Selected checkpoint | Optimizer step 28,000; approximately 1.669 row epochs |
| Planned schedule | 32k steps, fused AdamW, peak LR 1e-4 |
| LR schedule | 960-step warmup, cosine decay toward 1e-5 at 32k |
| Batching | Duration/token-aware row epochs; up to 24 short or one long example per GPU; accumulation one |
| Loss | Global supervised-token mean; conditioning prefix and padding masked |
| Augmentation | Probability 0.50; noisy_v3 phone/radio/Teams weights 1/1/1.5; no speed perturbation |
| Checkpoints/evaluation | Every 2k steps, plus evaluation at step zero; external single-GPU evaluators |
The corpus contains 23,350,245 target rows across 20 sources. Sources are shuffled by row epoch without oversampling to meet keyword targets. Different languages/styles can share audio; these are not 23 million independent recordings. The mix comprises:
Training uses each source's text field. For Norwegian targets, applicable
sources use upstream NormForm normalisation, so spelling variants can differ
from evaluation references. Keyword annotations populate SYSTEM context, not
the target. Training manifests and audio are not distributed in this model repo.
Exact source IDs/revisions are recorded in release_provenance.json.
The selected 28k evaluation was still queued when this release was prepared. No 24k, 0.10-run, Lunde or base-model scores should be attributed to the published 28k weights. Completed checkpoint evaluations and prediction reports are tracked in the internal W&B report run.
For context only, the earlier 24k checkpoint of the same .50 run had:
| Evaluation | Reading WER | Verbatim WER |
|---|---|---|
| Bokmål short, four-domain aggregate | 10.60% | 10.74% |
| Nynorsk short, four-domain aggregate | 14.86% | 14.53% |
| English translation, four-domain aggregate | 24.49% | 25.61% |
| Natural NB-tale long cohort | — | 19.73% |
At that earlier checkpoint, reading-optimised noisy-NST WER was studio 2.58%, room_far 6.29%, Teams 5.56%, MELPe2400 4.51%, MELPe1200 8.14%. These are greedy corpus-level WERs, not means of sample WER. Short aggregates exclude NB-tale and Fleurs; noise and long cohorts are scored separately. Each short language cohort has 400 unique clips/four domains, noisy NST has 100 clips per condition, and the long cohort contains only seven recordings. The references are pinned; detailed revisions are in release provenance.
Empty-reference output is not necessarily hallucination. Earlier dashboards called any nonempty prediction on a no-caption reference a hallucination. Maintainer listening review of flagged 24k examples identified faint genuine speech/voices. Those examples must not be presented as confirmed invented speech. We have not silently changed the references, recalculated official metrics, or claimed that every output is grounded. Background-speech rejection and invented content require separate, audited evaluation.
This private beta is checkpoint-28000, augmentation=0.50, from the fresh
Bokfink02 0.6B production-comparison run, Slurm 2563783. Internal run name:
NB-ASR-QWEN06-bokfink02-64gpu-32k-aug50-20261017.
It is not the .10 model, not checkpoint-29624, and not a completed 32k run.
The allocation timed out at approximately 29,624 updates; the maintainers
selected the last full scheduled 28k checkpoint. The LR horizon was not
compressed to 28k and no additional recovery/alignment fine-tuning was applied.
Weights, tokenizer, template and processor files are published byte-for-byte
from the selected checkpoint. release_provenance.json records SHA-256 hashes
and a source-revision inventory. inference.py and this model card are release
support files, not modifications to the checkpoint. Optimizer/scheduler/RNG
states, Trainer state, training arguments, logs, manifests, audio, transcripts
and credentials are deliberately excluded. Full recovery state remains in
internal storage.
Release verification covers checkpoint identity, tensor/tokenizer dimensions, prompt serialisation, package API/source compatibility, private Hub visibility and uploaded-file identity. The newly documented vLLM-plus-aligner path has not been executed end-to-end on a GPU as part of this publication; treat examples as integration starting points and verify on your deployment hardware.
Developed within NB-ASR at the National Library of Norway, using the Qwen architecture and the work of the NB-ASR data, infrastructure and evaluation teams.
NbAiLab/Qwen3-ASR-0.6B-custom-tokenizer