Results
Measured end to end, encoder included, at batch size 1 on one RTX 3090 in fp16. The test used 60 clips of at most 30 s
from each test set of the open Danish ASR leaderboard.
"Identical" compares against edda's own greedy generate() output.
Table with columns: test set, identical, tokens per edda pass, speed-up, edda greedy → hurtig| test set | identical | tokens per edda pass | speed-up | edda greedy → hurtig |
|---|
| FTSpeech | 60/60 | 9.31 | 3.22× | 407 → 126 ms |
| FLEURS da_dk | 60/60 | 5.56 | 2.57× | 467 → 182 ms |
| CoRal-v3 conversation | 60/60 | 5.63 | 2.23× | 298 → 134 ms |
| CoRal-v3 read-aloud | 60/60 | 4.56 | 1.99× | 291 → 147 ms |
| Common Voice Danish | 59/60 | 5.41 | 1.91× | 218 → 114 ms |
| all | 299/300 | 5.94 | 2.39× | 336 → 140 ms |
The one clip that differs is a half-precision near-tie. Verifying a block of tokens in one pass can flip a choice
between two almost equally likely tokens, compared with decoding them one at a time.
Greedy, not beam search. Edda's default decoding is beam search with 5 beams, and that is what its published WER of 8.65
uses. Hurtig reproduces edda's greedy output, which has a somewhat higher WER than 5-beam search. Use plain edda with beams
if you need the last bit of accuracy, and hurtig if you need speed.
Usage
# pip install transformers torch safetensors huggingface_hub soundfileimport sys, soundfile as sffrom huggingface_hub import snapshot_download path = snapshot_download("syvai/edda-v0.2-large-hurtig")sys.path.insert(0, path)from hurtig import load, transcribe model, drafter, processor = load(path) # edda + drafter on CUDA in fp16audio, sr = sf.read("clip.wav", dtype="float32") # mono, 16 kHz, at most 30 sprint(transcribe(model, drafter, processor, audio, sampling_rate=sr))
hurtig.spec_generate(model, drafter, mel) returns the token ids and the number of tokens accepted per edda pass.
The repo still loads as plain edda: WhisperForConditionalGeneration.from_pretrained("syvai/edda-v0.2-large-hurtig")
ignores the drafter files.
Limitations:
- Batch size 1 only.
- Danish transcription without timestamps only (prompt
<|da|><|transcribe|><|notimestamps|>).
- Clips of at most 30 s; longer audio has to be chunked first.
The drafter
hurtig.py follows z-lab/dflash's DFlash2DraftModel, adapted to Whisper:
- Block drafting. A block is the last verified token followed by 15 mask slots. Each slot predicts its own token in a
single forward pass.
- Context from edda. Hidden states from edda decoder layers 1, 8, 15, 22 and 29 are concatenated and passed through a
linear layer and RMSNorm. The result is injected as extra keys and values into each draft layer's self-attention.
- Audio. Each draft layer also cross-attends to edda's encoder output.
- DFlash2 additions. A grouped two-tap dynamic causal convolution sits around self-attention and the MLP. A candidate
selector takes the top 16 tokens per slot and picks a consistent path with a rank-256 pairwise score.
- Initialisation and size. The 5 draft layers start as copies of edda decoder layers 0, 8, 16, 23 and 31. Token
embeddings, positions and the output head are edda's own, frozen and not stored. The drafter has 170M trainable
parameters, stored in fp16 as
drafter.safetensors.
Training. The drafter was trained for 20k steps on edda's own greedy transcripts of 80k Danish training clips. The audio
came from FTSpeech, CoRal-v3, NST, FLEURS and Common Voice train splits, in edda's training mix. It learns to predict what edda
will write, not the reference transcripts. Loss is DFlash's position-decayed cross-entropy (γ = 7) plus a cross-entropy loss
on the selector.
License and attribution
Apache License 2.0, the same as edda.
- Edda v0.2 large (
model.safetensors, config.json, generation_config.json, the tokenizer and preprocessor files) is
redistributed unchanged from danish-foundation-models/edda-v0.2-large.
Edda was trained by the Alexandra Institute within the CoRal project and released by Danish Foundation Models under the
Apache License 2.0. Its base model, openai/whisper-large-v3, is MIT-licensed.
- The drafter (
drafter.safetensors, drafter_config.json, hurtig.py) was trained by syv.ai. It is
a derivative of edda: it is initialised from edda's decoder layers and trained on edda's outputs.
- Method: DFlash (arXiv:2602.06036) and DFlash2 by z-lab
(github.com/z-lab/dflash).
The training audio corpora carry their own licenses; see the respective dataset cards linked from edda's model card.