feat: fine-tune Moonshine's streaming models - #29
Merged
Conversation
added 2 commits
August 26, 2026 00:24
Lemonade now serves Moonshine-Medium-Streaming, and the streaming models carry their own neural VAD, which makes them the interesting target for this project. They are a separate architecture in transformers, moonshine_streaming with MoonshineStreamingForConditionalGeneration and MoonshineStreamingProcessor, not a flag on the offline model. They fit the existing seq2seq path: same raw waveform in input_values, same Wav2Vec2 feature extractor, English-only, and unlike offline Moonshine the tokenizer already carries a pad token, so no fallback is needed there. Two things had to change. The encoder reshapes its input to [batch, -1, 80], one 5 ms frame at 16 kHz, and raises on any other length. Padding a batch to its longest clip lands on a multiple of 80 only by luck. Architecture gained pad_to_multiple and the collator honours it. This did not show up in a synthetic test because 16000 and 24000 both happen to divide by 80; it appeared on the first real batch as "shape '[4, -1, 80]' is invalid for input of size 4246272". Name-based detection resolved moonshine-streaming-small to offline Moonshine, because hub ids use hyphens while model_type uses underscores and "moonshine" is a prefix of "moonshine_streaming". Detection now flattens separators and takes the longest match. Verified against the real checkpoint on gfx1151 with ROCm torch: architecture detected as moonshine_streaming, LoRA at 327,680 of 140,644,025 parameters (0.23%), batches collated to a frame-aligned length with an attention mask, and training running on the GPU. Note the medium model Lemonade serves, moonshine-ai/moonshine-streaming, ships as ONNX graphs only and cannot be fine-tuned. moonshine-streaming-small is the transformers checkpoint.
They build a real Wav2Vec2FeatureExtractor, so they need torch and transformers. CI installs only the dev extra, where they failed with ModuleNotFoundError.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lemonade now serves
Moonshine-Medium-Streaming, and the streaming models carry their own neural VAD, which makes them the interesting target for this project. They are a separate architecture in transformers,moonshine_streamingwithMoonshineStreamingForConditionalGenerationandMoonshineStreamingProcessor, not a flag on the offline model.They fit the existing seq2seq path: same raw waveform in
input_values, same Wav2Vec2 feature extractor, English-only, and unlike offline Moonshine the tokenizer already carries a pad token.Two things had to change, and only running it found them
Frame alignment. The encoder reshapes its input to
[batch, -1, 80], one 5 ms frame at 16 kHz, and raises on any other length. Padding a batch to its longest clip lands on a multiple of 80 only by luck.Architecturegainedpad_to_multipleand the collator honours it.A synthetic test passed because 16000 and 24000 both divide by 80. The first real batch gave:
Name detection.
moonshine-streaming-smallresolved to offline Moonshine, because hub ids use hyphens,model_typeuses underscores, andmoonshineis a prefix ofmoonshine_streaming. It would have silently trained with the wrong processor. Detection now flattens separators and takes the longest match.Verified on real hardware
gfx1151, ROCm torch, real MDC dataset:
Training runs and the loss moves. Two honest caveats.
Throughput is roughly 46 s/step at batch 4 on this iGPU, so a real run is hours.
The mid-training eval crashed the GPU queue:
at batch 34 of 193, during
predict_with_generate. That is the gfx1151 instability AMD's own support matrix implies, not something this PR introduces, and Whisper runs on the same box have completed eval fine. Worth knowing before planning a long run: consider--eval-stepsbeyond--max-stepsto skip mid-training eval on this hardware.Not covered
moonshine-ai/moonshine-streaming, the medium model Lemonade serves, ships as ONNX graphs with no PyTorch weights and cannot be fine-tuned.moonshine-streaming-smallis the transformers checkpoint. Serving and fine-tuning are different artifacts here.406 tests pass.