CoolFace
Modelpublic

kristijonas/kmynas-parakeet-lt-v2

sourceHugging Facecc-by-4.0updated 1mo agoView on Hugging Face
1likes46downloads
Model Card

Kmynas Parakeet LT v2

Lithuanian speech recognition that emits punctuation and capitalisation directly, with no separate restoration pass. FastConformer encoder, Token-and-Duration Transducer decoder, 0.6B parameters.

Trained from nvidia/parakeet-tdt-0.6b-v3 (revision 541d1f9) on 1,196.4 hours of punctuated Lithuanian — seven times the data behind v1 — and initialised from the base model rather than continued from v1, so the two remain independently comparable.

Results

Held-out LIEPA-3, carved before training. WER with punctuation and case stripped, and as actually produced:

setWERWER as produceddeletionsword retention
telephone speech6.8314.360.53%1.003
mixed validation15.1326.202.01%0.987
dialect (12 unseen speakers)26.8436.593.60%0.977

These are not comparable to FLEURS or VoxPopuli figures published for v1, Noctra or Paprika — different test sets entirely. Quoting them side by side would be wrong.

Quality improved monotonically across every checkpoint and every set; the final step was the best on all three, so the loss curve had not flattened at 2.39 epochs.

checkpointtelephonevalidationdialect
step 2,00017.3728.4840.66
step 6,0008.2319.0933.13
step 15,0006.8315.1326.84

Held-out design, stated honestly

  • —Dialect evaluation is genuinely speaker-independent — 12 whole speakers, three per dialect region, appearing nowhere in training. It is the honest generalisation signal here.
  • —Telephone evaluation is not. LIEPA-3's spontaneous config publishes no speaker or session identifier at all — file_hash is unique per row — so the held-out unit is a whole parquet shard used as a proxy. Adjacent utterances from one call may sit on both sides. Treat 6.83 as a shard-level estimate.
  • —Rows within one token edit of a training row were removed from the held-out side, so near-duplicates cannot inflate these numbers.

Training

data1,196.4 h / 1,604,270 utterances, LIEPA-3, punctuated
sourcesPhone 504.0 h, Radio 462.9 h, read 93.0 h, Dictaphone 90.7 h, other 45.7 h
initialisationbase parakeet + 3 spliced vocabulary tokens („ “ –)
effective batch256 (micro 16 × accumulation 16)
learning rate5.5e-4 AdamW, cosine → 1e-6, 1,500 warmup
schedule15,000 steps ≈ 2.39 epochs

Punctuation was restored on the targets by an LLM behind a word-preservation gate — any row whose word sequence changed was rejected, not repaired. Capitalisation is preserved as produced, including 173,050 training rows that begin lowercase. Those are genuine mid-sentence fragments: the lowercase rate tracks each source's segmentation structure (17.9% in the segmented phon config against 0.06% in whole-sentence read), and forcing capitals would have taught the model to capitalise mid-sentence.

Every target was re-encoded with the extended tokenizer before training and rows producing <unk> were quarantined, so the vocabulary gap that made v1 emit ⁇ cannot recur.

Limitations

  • —Borrowed English technical vocabulary is the dominant error class — spykerių for speakers, kuopi peis for copy-paste, KR kodas for QR kodas, and the same word spelled inconsistently within one recording. A new version with additional training data is in the works.
  • —No far-field or reverberant audio in the training mix. Phone is codec-limited, Radio close-mic broadcast, read studio, Dictaphone close-mic. Behaviour in a reverberant hall with a distant microphone is unmeasured.
  • —Trained on 0.5–15 s utterances. Long audio must be chunked, cut at pauses rather than on a fixed grid.
  • —The tokenizer has no word-initial ▁„, so „ encodes as two tokens and the model occasionally drops the space, producing knyga„Užrašęs. Restore it in post-processing; Lithuanian always spaces before an opening quote.
  • —Cannot emit ” (U+201D), ;, (, ) or —. Em dashes were normalised to – during training.

Use

python
import nemo.collections.asr as nemo_asr
model = nemo_asr.models.ASRModel.restore_from("kmynas-parakeet-lt-v2.nemo",
                                              map_location="cpu")
model = model.cpu().eval()
print(model.transcribe(["chunk.wav"], batch_size=4)[0].text)

Audio must be 16 kHz mono. Runs several times faster than real time on CPU alone; on GPU, RTF is around 0.026.

Run in fp32 or bf16 — not fp16. In half precision the greedy TDT decode occasionally emits a token id outside the 8,195-piece vocabulary (a blank or duration slot leaking into the hypothesis), and detokenisation then raises IndexError: OUT_OF_RANGE: piece id is out of range. Deterministic on the affected audio; absent at fp32 and absent at the step-6000 checkpoint, so it emerged late in training. bf16 keeps fp32's exponent range and avoids the overflow path. If fp16 is unavoidable, filter ids >= vocab_size before detokenising, or retry the failing chunk in fp32.

Licence and attribution

CC BY 4.0, inheriting LIEPA-3 (VU, VDU, LKI), published via CLARIN-LT: <https://clarin-repo.lt/items/0a04648e-ba4e-4e6f-9161-a2d01e8e9fdb/full>

Base model nvidia/parakeet-tdt-0.6b-v3, CC BY 4.0.

bibtex
@misc{kmynas_lt_v2,
  title  = {Kmynas Parakeet LT v2},
  author = {Kristijonas Jakubsonas},
  year   = {2026},
  url    = {https://huggingface.co/kristijonas/kmynas-parakeet-lt-v2}
}