feat: Phase 42 β Audio Modality (v4.0.0-alpha.2) - #49
Merged
Conversation
Add a fourth input sense β audio β following the exact frozen-encoder-plus-trainable-projector pattern v2 Β§24 established for vision and v3 Β§35β36 reused for video and documents. - New aarambh-studio-audio crate: FrozenAudioEncoder (AST-style transformer, SafeTensors load), AudioPreprocessor (pure-Rust WAV decode + Hann window + radix-2 FFT + mel filterbank, zero new deps), AudioProjector, interleave_audio_tokens, AudioQaExample JSONL. - Tokenizer: <audio>/<audio_end> tokens (IDs 15/16), AUDIO_SPECIAL_TOKENS, validate_audio_special_tokens, upgraded_for_audio. - convert --upgrade-audio-vocab (insertion at ID 15, +2 rows). - [vision.audio] config block + AudioTrainingConfig. - finetune audio-dora / audio-qdora subcommands (run_audio_vlm_dora_from_config two-stage trainer). - infer --audio flag + AudioSafetyAdapter. - eval audio-qa / audio-qa-smoke task. - Smoke scripts, configs, fixture generator, data-prep script, docs/phase42_audio.md. - Bump workspace version 4.0.0-alpha.1 -> 4.0.0-alpha.2; release audit EXPECTED_PACKAGES 19 -> 20. - Fix: BpeTokenizer::encode now recognizes AUDIO_SPECIAL_TOKENS so <audio>/<audio_end> are emitted as single tokens, not BPE-split. - Tests: 4 mandated Phase 42 proof tests (frozen-encoder gradient isolation, projector-only stage, fusion length, thinking composability) + regression tests for the encode fix + unit tests.
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.
Summary
Phase 42 adds a fourth input sense β audio β to aarambh-studio,
following the exact frozen-encoder-plus-trainable-projector pattern
v2 Β§24 established for vision and v3 Β§35β36 reused for video and
documents. A frozen, pretrained audio spectrogram transformer
converts a log-mel spectrogram into a grid of patch embeddings; a
small trainable projector maps those into the decoder's
d_modelspace; the result is spliced into the token sequence at the
<audio>special token position. Nothing about the decoder, thethinking engine, grammar-constrained tool calling, or long-horizon
tool chains changes β audio is just another sense feeding the same
fusion mechanism.
This is the v4.0.0-alpha.2 release tag, the first Phase 42
deliverable defined in
ROADMAP_V4.mdΒ§Phase 42 andARCHITECTURE_V4.mdΒ§56.What's new
New crate:
aarambh-studio-audio(Layer 3)encoder.rsFrozenAudioEncoderβ AST-style transformer over mel-spectrogram patches;load_pretrainedviaVarBuilder::from_mmaped_safetensors(same loading path as CLIP)preprocess.rsMelSpectrogramConfig+AudioPreprocessorβ pure-Rust WAV decode (PCM 8/16/24/32-bit + 32/64-bit float), linear resampling, Hann window, radix-2 Cooley-Tukey FFT, triangular mel filterbank, log-mel normalization β zero new dependenciesprojector.rsAudioProjectorβ two-layer GELU MLP mirroringVisionProjectorexactlyfusion.rsinterleave_audio_tokens()β generalizesinterleave_image_tokensinstruct_data.rsAudioQaExample+load_audio_qa_jsonl(caption, QA, LLaVA conversation formats)Tokenizer
<audio>/<audio_end>reserved special tokens (IDs 15 / 16)AUDIO_SPECIAL_TOKENStable (17 entries β strict superset of the Phase 36 document table)BpeTokenizer::validate_audio_special_tokens()BpeTokenizer::upgraded_for_audio()(insertion at ID 15, +2 rows, shifts learned IDs β₯ 15)CLI
convert --upgrade-audio-vocabβ applies the vocabulary migration to a SafeTensors checkpoint + tokenizer togetherfinetune audio-dora/audio-qdoraβ self-contained two-stage DoRA trainer (run_audio_vlm_dora_from_config) reusingDoraAarambhModel,AdamW::from_varmap,CosineScheduleWithWarmup,accumulate_for_optimizer,cross_entropy_loss,save_adapterinfer --audio <path>β conflicts with--image/--video/--document(one modality per call, same discipline every prior modality flag holds); backed byAudioRuntime,build_audio_prompt_embeddings,project_audio_tokens,run_audio_infer, and anAudioSafetyAdapterimplementingSafetyGeneratoreval --tasks audio-qa/audio-qa-smokeβ implements the sharedEvalTasktraitConfig
[vision.audio]block (AudioTrainingConfig:audio_root, encoder config/weights paths,mel: MelSpectrogramConfig,encoder_batch_size,feature_cache_entries) under the shared[vision]multimodal blockconfigs/audio_qa_smoke.toml,configs/audio_qa_smoke_infer.tomlScripts & docs
scripts/phase42_make_audio_smoke_fixture.pyβ synthetic sine-wave WAVs + tiny random-init audio encoder + projectorscripts/phase42_prepare_audio_data.shβ data-prep orchestrator (free + public policy, synthetic fallback)scripts/phase42_smoke.shβ full smoke chain (fixture β convert β finetune β merge β infer β eval)docs/phase42_audio.mdβ full phase documentationWorkspace
4.0.0-alpha.1β4.0.0-alpha.2EXPECTED_PACKAGES19β20finetune audio-dora --helpandfinetune audio-qdora --helpBug fix included
While verifying the audio smoke end-to-end, I found that
BpeTokenizer::encodeonly recognizedSPECIAL_TOKENS(the 15-entrydocument table) for special-token splitting, so
<audio>/<audio_end>(IDs 15/16) were silently BPE-split into characters βbreaking audio fusion at the placeholder. Fixed:
encodenow usesAUDIO_SPECIAL_TOKENS(the 17-entry superset); the per-token vocabfilter makes this safe for text/vision/video/document tokenizers too.
Three regression tests pin the fix.
Tests
The four Phase 42 proof obligations from
ROADMAP_V4.md:frozen_audio_encoder_never_receives_gradientsaarambh-studio-audioprojector_pretrain_stage_trains_only_projector_weightsaarambh-studio-audioaudio_token_fusion_produces_expected_sequence_lengthaarambh-studio-audiointerleave_audio_tokensproducesseq - 1 + audio_tokenslengththinking_controller_behaves_identically_after_audio_contextaarambh-studio-audioPlus unit tests for WAV decode (PCM 16-bit + 32-bit float stereo),
FFT frequency recovery, mel frame counting, projector output width,
fusion placeholder validation, JSONL parsing (caption + QA +
conversation), and three tokenizer-table consistency tests + three
regression tests for the encode fix.
CI gates (all green locally)
cargo fmt --all --checkcargo check --workspace --all-targets --lockedcargo clippy --workspace --all-targets --locked -- -D warnings -D clippy::undocumented_unsafe_blockscargo test --workspace --no-fail-fast --lockedRUSTDOCFLAGS="-D warnings -D missing_docs" cargo doc --workspace --no-deps --lockedscripts/phase28_release_audit.shfind scripts -type f -name '*.sh' -print0 | xargs -0 -n1 bash -ncargo build --release --locked -p aarambh-studio--help, incl. the newaudio-dora/audio-qdora)Audio smoke β verified end-to-end
Trained a tiny model β
convert --upgrade-audio-vocab(517 β 519 tokens)β
infer --audio mid_tone.wavsucceeded (WAV β mel β frozen encoder βprojector β
<audio>fusion β decoder generation,finish_reason=MaxTokens) βeval --tasks audio-qa-smokeproduced ascorecard. Output is gibberish (expected from a 2-layer / 20-step
model on synthetic text) β the pipeline is what's verified.
Scope and boundaries (consistent with prior modality phases)
rustfftor audio-DSP dependencyDiffstat
New crate
crates/aarambh-studio-audio/(6 source files, ~2050 LOC).Touches: tokenizer, convert, train config, finetune, infer, eval,
main binary Cargo.toml, CI workflow, release audit, README, ROADMAP_V4,
ARCHITECTURE_V4, CHANGELOG, Cargo.toml, Cargo.lock.
Checklist
cargo fmt --checkclean)TODO/FIXME/unimplemented!markers (release-audit enforced)4.0.0-alpha.2) andpublish = falseCargo.lockis tracked and consistent.safetensors/checkpoints//adapters/excluded)[ ]unfinished tasks in ROADMAP.md / ROADMAP_V2.md / ROADMAP_V3.mddocs/phase42_audio.md) and cross-linked from READMEv4.0.0-alpha.2v4.0.0-alpha.2createdRelated
ROADMAP_V4.mdΒ§Phase 42ARCHITECTURE_V4.mdΒ§56