ASR fine-tuning (v0.71.32)
soup train with task: asr fine-tunes OpenAI Whisper speech-recognition models on your own audio, locally. Data is plain JSONL rows of {"audio": "clip.wav", "text": "the transcript"}: clips decode to 16 kHz mono log-mel input features, transcripts become the decoder labels, and the trainer wraps Hugging Face Seq2SeqTrainer + WhisperProcessor. whisper-tiny (39M) and whisper-base (74M) train on a 4 GB GPU.
Config
base: openai/whisper-tiny
task: asr
data:
train: ./data/train.jsonl
format: asr # rows: {"audio": "clip.wav", "text": "hello world"}
audio_dir: ./data/audio # audio paths resolve here (containment-checked)
training:
epochs: 3
lr: 1e-4
batch_size: 2
asr_language: en # optional; pins + persists the decoder prefix
asr_task: transcribe # transcribe | translate
asr_lora: true # LoRA on q/v projections; default is full fine-tune
lora: { r: 16, alpha: 32, target_modules: [q_proj, v_proj] }
output: ./outpip install 'soup-cli[train,audio]'
soup recipes use whisper-tiny-asr # or whisper-base-asr / whisper-large-v3-asr
soup trainConfig fields
| Field | Default | Meaning |
|---|---|---|
asr_language | (none) | Decoder language prefix (e.g. en). Persists to an asr_generation.json sidecar next to the weights, so inference restores it automatically. |
asr_task | transcribe | transcribe or translate. Also persisted to the sidecar. |
asr_lora | false | true trains LoRA on the q/v projections instead of full fine-tuning. |
The cross-validator requires backend: transformers (so mlx / unsloth are rejected) and footgun-rejects asr_* fields when the task is not asr; a separate trainer-side gate rejects a non-Whisper base before any weight download.
Inference + WER/CER
soup infer --task asr --model ./out --input eval.jsonl --output preds.jsonl \
--audio-dir ./data/audio [--asr-language en] [--asr-task transcribe]--model loads a full Whisper model or a PEFT/LoRA adapter dir. Input rows are {"audio": path} with an optional "text" reference; when references are present, each output row carries transcription, wer and cer, plus a corpus WER summary (sum of edits over sum of reference words, not a mean of per-row rates). The metrics are pure-Python word- and char-level Levenshtein with no new dependency, and word accuracy (1 - WER) plugs into soup ship as a higher-is-better task metric, so the SHIP / DON'T-SHIP verdict works for speech models too.
WER/CER use a light normalizer (casefold, strip surrounding punctuation, collapse whitespace), deliberately not the full Whisper normalizer: good for before/after deltas, not leaderboard-comparable absolutes.
Recipes
| Recipe | Base | Size | Status |
|---|---|---|---|
whisper-tiny-asr | openai/whisper-tiny | 39M | Live, validated on a 4 GB RTX 3050 |
whisper-base-asr | openai/whisper-base | 74M | Live, fits a 4 GB GPU |
whisper-large-v3-asr | openai/whisper-large-v3 | 1.5B | Parse-tested; needs a 16 GB+ GPU |
A smolvlm-256m-sft tiny-VLM recipe ships alongside (parse-tested, target_modules pinned to q/v); live vision SFT for Idefics3-style processors is tracked in issue #302.
Honesty
Proof-of-mechanism only. The live validation is a memorization run on a single RTX 3050: WER 1.000 to 0.000 and loss 7.2 to 0.0005 at 0.4 of 4 GB VRAM. That proves the loop trains end to end; real accent or domain gains need real audio. The release also fixed the hardware-fit gate mis-sizing Whisper checkpoints as 7B models, which would have wrongly blocked ASR training on consumer GPUs.
Security
Audio decodes only through the hardened loader (a soundfile pre-probe before read, symlink rejection, O_NOFOLLOW, byte caps), never through datasets auto-decode. data.audio_dir is containment-checked (realpath + commonpath); UNC paths and traversal are rejected. A missing [audio] extra, a bad audio path, or a non-Whisper base all fail with a friendly error before a GPU hour.
See also
- Vision & Audio — the audio-understanding (Qwen2-Audio) and vision paths.
- Modality II — TTS, the audio-out counterpart to ASR's audio-in.
- soup ship — gate a speech model on word accuracy plus no forgetting.
- Recipes — all 142 ready-made configs.