Instructions to use pluttodk/milo-asr with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use pluttodk/milo-asr with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("automatic-speech-recognition", model="pluttodk/milo-asr")# Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("pluttodk/milo-asr") model = AutoModelForMultimodalLM.from_pretrained("pluttodk/milo-asr", device_map="auto") - Notebooks
- Google Colab
- Kaggle
license: openrail
language:
- da
base_model: Qwen/Qwen3-ASR-1.7B
tags:
- automatic-speech-recognition
- danish
- qwen
- asr
- speech-to-text
- coral
- streaming
datasets:
- alexandrainst/coral
library_name: transformers
pipeline_tag: automatic-speech-recognition
metrics:
- wer
- cer
model-index:
- name: milo-asr
results:
- task:
type: automatic-speech-recognition
name: Speech Recognition
dataset:
type: alexandrainst/coral
name: CoRal v2 Test
split: test
metrics:
- type: wer
value: 18.47
name: WER
- type: cer
value: 7.86
name: CER
Milo-ASR: Dansk talegenkendelses model
Milo-ASR er en dansk ASR-model bygget oven på Qwen3-ASR-1.7B, som er finetunet på CoRal v2-datasættet for at blive god til dansk.
Kort fortalt
| Feature | Værdi |
|---|---|
| WER på CoRal v2 | 18,47% (14% bedre end hviske-v3-conversation) |
| CER på CoRal v2 | 7,86% (11% bedre end hviske-v3-conversation) |
| Real-Time Factor | 0,087 (43% hurtigere end hviske-v3-conversation) |
| Modelstørrelse | ~1,7B parametre |
Hvad Milo-ASR kan (nedarvet fra Qwen3-ASR)
- Streaming/realtidstransskription via vLLM backend
- Sanggenkendelse – Milo-ASR kan transskribere tale i lyd med baggrundsmusik
- Tidsstempler på ordniveau via forced alignment
- 30+ sprog (optimeret til dansk)
- Op til 20 minutter pr. kald – du behøver ikke hakke lyden op i småbidder
Sammenligning med andre modeller
CoRal v2 testsæt (9.123 eksempler, ~17,3 timer)
| Model | WER | CER | RTF | Gennemløb | Parametre |
|---|---|---|---|---|---|
| Milo-ASR | 18,47% | 7,86% | 0,087 | 1,69 eks./s | ~1,7B |
| hviske-v2 (Whisper Large v2) | 12,74% | 4,94% | 0,154 | 0,95 eks./s | ~1,5B |
| hviske-v3-conversation (Whisper Large v3) | 21,47% | 8,79% | 0,153 | 0,95 eks./s | ~2B |
| Whisper Large v3 Turbo | 38,54% | 13,73% | 0,064 | 2,29 eks./s | ~0,8B |
| Qwen3-ASR-1.7B (base) | 46,03% | 18,85% | 0,100 | 1,46 eks./s | ~1,7B |
Milo-ASR vs. hviske-v3-conversation (Whisper Large v3):
- 14% lavere Word Error Rate (18,47% vs. 21,47%)
- 11% lavere Character Error Rate (7,86% vs. 8,79%)
- 43% hurtigere inferens (RTF: 0,087 vs. 0,153)
- 15% færre parametre (~1,7B vs. ~2B)
Bemærk: hviske-v2 (Whisper Large v2) klarer sig bedre end Milo-ASR på WER og CER. Til gengæld er Milo-ASR næsten dobbelt så hurtig (RTF 0,087 vs. 0,154), så hvis hastighed er vigtig for dig, er Milo-ASR det oplagte valg.
Sammenligningsplots
Kom i gang
Installation
pip install qwen-asr transformers torch
Basis brug
from qwen_asr import Qwen3ASRModel
# Indlæs Milo-ASR
model = Qwen3ASRModel.from_pretrained(
"pluttodk/Milo-ASR",
dtype="bfloat16",
device_map="cuda:0",
)
# Transskriber en dansk lydfil
results = model.transcribe(
audio="sti/til/dansk_lyd.wav",
language="Danish",
)
print(results[0].text)
Avanceret brug
Batch-transskription
Kør flere filer på én gang:
from qwen_asr import Qwen3ASRModel
model = Qwen3ASRModel.from_pretrained(
"pluttodk/Milo-ASR",
dtype="bfloat16",
device_map="cuda:0",
max_inference_batch_size=16,
)
audio_filer = ["lyd1.wav", "lyd2.wav", "lyd3.wav"]
results = model.transcribe(
audio=audio_filer,
language="Danish",
)
for i, result in enumerate(results):
print(f"Fil {i+1}: {result.text}")
Transskription med tidsstempler
Få tidsstempler på ordniveau via forced aligner:
from qwen_asr import Qwen3ASRModel
model = Qwen3ASRModel.from_pretrained(
"pluttodk/Milo-ASR",
forced_aligner="Qwen/Qwen3-ForcedAligner-0.6B",
dtype="bfloat16",
device_map="cuda:0",
)
results = model.transcribe(
audio="sti/til/lyd.wav",
language="Danish",
return_time_stamps=True,
)
for item in results[0].time_stamps.items:
print(f"{item.start_time:.2f}s - {item.end_time:.2f}s: {item.text}")
Streaming i realtid (vLLM backend)
Hvis du vil have live transskription, fx fra en mikrofon:
from qwen_asr import Qwen3ASRModel
model = Qwen3ASRModel.LLM(
model="pluttodk/Milo-ASR",
gpu_memory_utilization=0.8,
)
state = model.init_streaming_state(
language="Danish",
chunk_size_sec=2.0,
)
import numpy as np
def lyd_stream():
"""Erstat med din faktiske lydstream fra mikrofon."""
for chunk in audio_chunks:
yield np.array(chunk, dtype=np.float32)
for lyd_chunk in lyd_stream():
state = model.streaming_transcribe(lyd_chunk, state)
print(f"Løbende transskription: {state.text}")
state = model.finish_streaming_transcribe(state)
print(f"Endelig transskription: {state.text}")
Direkte brug med Transformers
Vil du have fuld kontrol over modellen, kan du bruge Transformers direkte:
from transformers import AutoModel, AutoProcessor
import torch
import librosa
model = AutoModel.from_pretrained(
"pluttodk/Milo-ASR",
trust_remote_code=True,
torch_dtype=torch.bfloat16,
device_map="cuda:0",
)
processor = AutoProcessor.from_pretrained(
"pluttodk/Milo-ASR",
trust_remote_code=True,
)
audio, sr = librosa.load("sti/til/lyd.wav", sr=16000, mono=True)
messages = [
{"role": "system", "content": ""},
{"role": "user", "content": [{"type": "audio", "audio": audio}]},
]
text = processor.apply_chat_template(
messages,
add_generation_prompt=True,
tokenize=False
)
text = text + "language Danish<asr_text>"
inputs = processor(text=[text], audio=[audio], return_tensors="pt", padding=True)
inputs = inputs.to(model.device).to(model.dtype)
output_ids = model.generate(**inputs, max_new_tokens=512)
transskription = processor.batch_decode(
output_ids[:, inputs["input_ids"].shape[1]:],
skip_special_tokens=True,
)[0]
print(transskription)
Sang og baggrundsmusik
Milo-ASR kan håndtere lyd med sang eller baggrundsmusik:
from qwen_asr import Qwen3ASRModel
model = Qwen3ASRModel.from_pretrained(
"pluttodk/Milo-ASR",
dtype="bfloat16",
device_map="cuda:0",
)
results = model.transcribe(
audio="sti/til/sang.wav",
language="Danish", # eller None for automatisk sproggenkendelse
)
print(results[0].text)
Om modellen
Beskrivelse
Milo-ASR er lavet ved at finetunet Qwen3-ASR-1.7B på CoRal v2-datasættet. Resultatet er en model, der er skarp til dansk tale og samtidig hurtig nok til at bruges i produktionsmiljøer og realtidsapplikationer.
- Udviklet af: Mathias Oliver Valdbjørn Rønnelund
- Modeltype: Encoder-decoder talegenkendelses model
- Sprog: Dansk (primært), med nedarvet flersproget understøttelse
- Licens: OpenRAIL
- Finetunet fra: Qwen/Qwen3-ASR-1.7B
Arkitektur
| Komponent | Specifikation |
|---|---|
| Audio Encoder | 24-lags transformer (1024 hidden dim, 16 attention heads) |
| Text Decoder | 28-lags transformer (2048 hidden dim, 16 attention heads) |
| Parametre i alt | ~1,7 milliarder |
| Præcision | bfloat16 |
| Lydinput | 16kHz mono WAV |
Træning
Træningsdata
Milo-ASR er finetunet på CoRal v2-datasættet, som er et dansk talekorpus med:
- Mange forskellige danske talere på tværs af alder, køn og dialekter
- Varierende optagelseskvalitet og lydmiljøer
- Naturlig samtaletale
- Oplæst tale
Træningsopsætning
Tilgang: Supervised Fine-Tuning (SFT) med chat template-formatering
Forbehandling:
- Lyd resamplet til 16kHz mono
- Chat template anvendt med systemprompt, lydinput og måltransskription
- Prefix masking så modellen kun trænes på transskriptionstokens
Hyperparametre:
| Parameter | Værdi |
|---|---|
| Basismodel | Qwen/Qwen3-ASR-1.7B |
| Læringsrate | 2e-5 |
| Batchstørrelse (per device) | 8 |
| Gradient accumulation steps | 4 |
| Effektiv batchstørrelse | 32 |
| Epoker | 3 |
| Warmup ratio | 0,1 |
| Weight decay | 0,01 |
| Max gradient norm | 1,0 |
| Præcision | bfloat16 |
| Optimizer | AdamW |
| LR scheduler | Lineært fald |
| Træningsskridt i alt | 23.448 |
Hardware: NVIDIA GPU'er (~25GB GPU-hukommelse per device)
Evaluering
Testdata
Milo-ASR er evalueret på CoRal v2-testsættet:
- 9.123 eksempler
- ~17,3 timers lyd
- Bred repræsentation af danske talere og optagelsesforhold
Metrikker
| Metrik | Beskrivelse |
|---|---|
| WER | Word Error Rate – andelen af forkert transskriberede ord (lavere er bedre) |
| CER | Character Error Rate – andelen af forkert transskriberede tegn (lavere er bedre) |
| RTF | Real-Time Factor – forholdet mellem procestid og lydvarighed (under 1,0 = hurtigere end realtid) |
Resultater
| Model | WER | CER | RTF | Gennemløb | Parametre |
|---|---|---|---|---|---|
| Milo-ASR | 18,47% | 7,86% | 0,087 | 1,69 eks./s | ~1,7B |
| hviske-v2 (Whisper Large v2) | 12,74% | 4,94% | 0,154 | 0,95 eks./s | ~1,5B |
| hviske-v3-conversation (Whisper Large v3) | 21,47% | 8,79% | 0,153 | 0,95 eks./s | ~2B |
| Whisper Large v3 Turbo | 38,54% | 13,73% | 0,064 | 2,29 eks./s | ~0,8B |
| Qwen3-ASR-1.7B (base) | 46,03% | 18,85% | 0,100 | 1,46 eks./s | ~1,7B |
Milo-ASR slår hviske-v3-conversation med 14% på WER og 11% på CER, og er samtidig 43% hurtigere. Sammenlignet med den utrænede Qwen3-ASR-1.7B basismodel falder WER fra 46,03% til 18,47% – et klart tegn på, at finetuning på CoRal v2 gør en stor forskel.
Citér modellen
Bruger du Milo-ASR i dit projekt, må du meget gerne citere:
@misc{Milo-ASR,
author = {Rønnelund, Mathias Oliver Valdbjørn},
title = {Milo-ASR: Danish ASR Model based on Qwen3-ASR},
year = {2025},
publisher = {HuggingFace},
url = {https://huggingface.co/pluttodk/Milo-ASR}
}
Og gerne også basismodellen og datasættet:
@article{qwen3asr,
title={Qwen3-ASR Technical Report},
author={Qwen Team},
journal={arXiv preprint arXiv:2601.21337},
year={2025}
}
@dataset{coral,
title={CoRal: A Danish Speech Corpus},
author={Alexandra Institute},
year={2024},
url={https://huggingface.co/datasets/alexandrainst/coral}
}
Tak til
- Qwen-teamet for Qwen3-ASR basismodellen
- Alexandra Instituttet for CoRal v2-datasættet


