Note: Gemma 4 (
google/gemma-4-E2B) is now the primary fine-tuning target. Gemma 3n remains supported. This document covers the original Gemma 3n integration; Gemma 4 uses the same pipeline (identical USM-style audio encoder, same LoRA targets, same collator).
Related: condensed developer notes — ../guides/apple-silicon/gemma3n.md. For Gemma 4 (separate Transformers / PEFT pin), see ../guides/apple-silicon/gemma4-guide.md.
This document outlines the integration of Google's Gemma 3n, a state-of-the-art open multimodal model, into this repository’s Gemma training stack. It covers parameter-efficient fine-tuning (PEFT) on Gemma 3n's audio capabilities, leveraging existing Apple Silicon (MPS) optimizations. The core of this project involves engineering a robust data pipeline to accommodate Gemma's unique audio processing requirements and extending the CLI wizard to provide a seamless, guided user experience for this new model family.
- Gemma 3n Audio Fine-Tuning: Adapt Gemma 3n for domain-specific audio transcription tasks.
- Parameter-Efficient Training: Utilize LoRA and QLoRA to fine-tune Gemma 3n on consumer hardware.
- Seamless Wizard Integration: A guided, zero-configuration workflow for setting up Gemma 3n training runs.
- Apple Silicon First: Optimized for PyTorch on MPS, leveraging unified memory for efficient training.
- Multimodal Data Pipeline: A new data processor to handle the Universal Speech Model (USM) feature extraction required by Gemma 3n.
Gemma 3n is integrated as the primary multimodal training path. The existing architecture (gemma_tuner/core/ops.py dispatch, gemma_tuner/models/gemma/finetune.py) implements training.
- Model Implementation: A new module at
gemma_tuner/models/gemma/finetune.pywill be created. It will leverage Hugging Face'stransformerslibrary to loadAutoModelForCausalLMandAutoProcessorfor Gemma 3n models. - Training Framework: The project will use the
trl.SFTTrainer, which is well-suited for Gemma's chat-based format. This requires a specialized data pipeline to format audio-text pairs into the required conversational structure. - Primary Toolkit: PyTorch with MPS is the designated framework for this task, as recommended in the developer field guide for its mature ecosystem (
peft,trl) and flexibility with complex multimodal models. MLX is explicitly avoided due to its current instability with Gemma's audio tower.
-
Data Preprocessing (The Critical Path):
- Challenge: Gemma's audio encoder uses Google's Universal Speech Model (USM), which requires a specific feature extraction process, unlike classic log-mel ASR pipelines.
- Solution: We will create a new data preparation script,
gemma_tuner/utils/gemma_dataset_prep.py. This script will use the officialtransformers.GemmaProcessorto handle all audio processing. This ensures perfect replication of the required feature extraction and tokenization.
-
Conversational Data Formatting:
- Challenge:
SFTTrainerfor Gemma requires input data in a specific chat format with special tokens (<bos>,<start_of_turn>,<end_of_turn>). - Solution: The new data prep script will include a function to transform simple
(audio, text)pairs into the required JSONL format with the correct conversational structure. The<bos>token will be prepended to every training example, a strict requirement for stable training.
- Challenge:
-
Numerical Stability on MPS:
- Challenge: Gemma was pre-trained using
bfloat16. The PyTorch MPS backend can be sensitive to floating-point precision, potentially leading toNaNloss values when using the defaultfloat16. - Solution: The training script (
gemma_tuner/models/gemma/finetune.py) and wizard will default to usingbfloat16(bf16=TrueinSFTConfig) when an MPS device is detected. If the hardware does not supportbfloat16, it will fall back to fullfloat32, and the user will be warned about increased memory usage.
- Challenge: Gemma was pre-trained using
The wizard has been successfully extended to make Gemma 3n a first-class citizen with full progressive disclosure support.
-
✅ Model family (Gemma only): The shipped wizard targets Gemma only; there is no alternate ASR family selector in the UI.
-
✅ Gemma Model Selection with Hardware Gating: When "Gemma" is selected, the wizard displays hardware-appropriate options.
? Which model do you want to fine-tune? ❯ gemma-4-e2b (~2B) - Faster, smaller memory footprint. ⭐ Recommended gemma-4-e4b (~4B) - Maximum capability, higher memory usage. gemma-3n-e2b-it (~2B) - Gemma 3n (legacy) gemma-3n-e4b-it (~4B) - Gemma 3n (legacy)Memory Gating: Uses
ModelSpecs.MODESwith 20% safety buffer to hide infeasible options based on available system memory. -
✅ Training Method Restriction: For Gemma models, only LoRA is available due to memory requirements.
? Choose your training method for Gemma: ❯ 🎨 LoRA Fine-Tune - Optimized for Gemma 3n on consumer hardware.Note: Standard fine-tuning is automatically hidden for Gemma models to prevent memory issues.
-
✅ Automatic Configuration Management: The wizard handles all Gemma-specific optimizations transparently:
- Data Type Optimization: Prefers
bfloat16on MPS; falls back tofloat32if unsupported - Attention Implementation: Forces
eagerattention for MPS stability - Chat Template: Automatically configures proper multimodal message formatting
- LoRA Configuration: Uses optimal settings (
rank=16,alpha=32) for Gemma architecture - Memory Settings: Applies conservative memory limits for stable training
- Data Type Optimization: Prefers
-
✅ Enhanced Confirmation Screen: The confirmation screen displays Gemma-specific configuration details:
┌─────────────────────────────────────┐ │ Training Configuration │ ├─────────────────────────────────────┤ │ Family: 💎 Gemma │ │ Model: gemma-4-e2b │ │ Method: 🎨 LoRA Fine-Tune │ │ Dataset: common_voice (50k) │ │ Data Type: bfloat16 │ │ Attention: eager │ │ LoRA Rank: 16 │ │ Device: Apple Silicon (mps) │ └─────────────────────────────────────┘
- ✅ Progressive Disclosure: Complex Gemma settings are handled automatically
- ✅ Hardware Awareness: Memory gating prevents selection of incompatible models
- ✅ Platform Optimization: Automatic MPS/CUDA/CPU configuration
- ✅ Error Prevention: Invalid combinations are prevented at selection time
- ✅ User Experience: Seamless flow with clear feedback and recommendations
To support Gemma, the configuration system will be extended with a new group and model profiles.
[group:gemma]
# Common settings for all Gemma models
attn_implementation = eager
dtype = bfloat16 ; Critical for MPS stability
optim = paged_adamw_32bit[model:gemma-3n-e2b-it]
base_model = google/gemma-3n-E2B-it
group = gemma
[profile:gemma-lora-test]
inherits = DEFAULT
model = gemma-3n-e2b-it
dataset = test_streaming
method = lora
lora_r = 16
lora_alpha = 32
target_modules = q_proj,k_proj,v_proj,o_proj- High Memory Requirements: Even with LoRA, fine-tuning Gemma 3n's audio tower is memory-intensive. Full SFT will be impractical on most consumer hardware.
- Data Pipeline Complexity: The dependency on the
GemmaProcessorand the specific chat template makes the data pipeline sensitive to format errors. Any deviation will lead to poor results. - Initial Scope: The initial integration will focus on LoRA fine-tuning for audio transcription. Other modalities (vision) and training methods (distillation) are out of scope for the first version.
- MLX Instability: As noted in the field guide,
mlx-lmhas known issues with Gemma's audio tower. This integration will only support the PyTorch MPS backend.
- Created
gemma_tuner/models/gemma/finetune.pywith Gemma 3n LoRA trainer- Loads
AutoModelForCausalLM+AutoProcessor - Prefers bf16 on MPS (probe); falls back to float32
- Uses eager attention; injects LoRA (
q_proj,k_proj,v_proj,o_projwith auto-discovery fallback) - Implements
DataCollatorGemmaAudiothat delegates multimodal packing to the processor - Integrates with existing dataset loader (
utils.dataset_utils.load_dataset_split) - Saves adapters and
train_results.json
- Loads
- Added Gemma routing in orchestrator:
gemma_tuner/scripts/finetune.pynow detectsgemmamodels and dispatchesgemma_tuner.models.gemma.finetune - Added environment preflight:
gemma_tuner/scripts/gemma_preflight.py(arm64, MPS availability, bf16 probe, memory tips) - Added quick profiler:
gemma_tuner/scripts/gemma_profiler.py(loads model, runs tiny forward, reports dtype/time/RSS) - Updated
config.ini- Added
[group:gemma]withdtype=bfloat16,attn_implementation=eager - Added
[model:gemma-3n-e2b-it]and[model:gemma-3n-e4b-it] - Added example
[profile:gemma-lora-test]usingtest_streaming
- Added
- Add
gemma_tuner/utils/gemma_dataset_prep.py(JSONL writer; optional if processor-based collator suffices) - Add
gemma_tuner/scripts/gemma_generate.py(load base + adapters; transcribe a WAV) - Wizard integration
- Gemma-only wizard flow (no multi-family selector required for shipping)
- Add Gemma models to wizard gating table for memory checks (
ModelSpecs.MODES) - Include Gemma models when user selects LoRA method in wizard model list
- Gemma-only method: LoRA (SFT hidden for now)
- Memory gating for E2B/E4B choices (uses ModelSpecs and available memory with 20% safety buffer)
- Confirmation screen: show dtype/attention for Gemma and enforce
attn_implementation=eagerin profile
- Tests
- Unit:
DataCollatorGemmaAudioproduces required keys;<bos>presence via processor template - Tiny overfit (16–64 samples) sanity on MPS (
scripts/gemma_tiny_overfit.py)
- Unit:
- Eval utilities
-
tools/eval_gemma_asr.py(WER/CER via jiwer)
-
- Docs
- Add README section with setup, preflight, example run and known caveats
Notes:
- bitsandbytes is not used on macOS; optimizer defaults to AdamW.
- TRL SFTTrainer was not assumed; using vanilla Trainer + custom collator for robustness.
python -c "import platform; print(platform.platform())" # Must show arm64
pip install --upgrade pip
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install transformers datasets accelerate peft jiwer soundfile
Recommended MPS env (memory pressure control):
export PYTORCH_MPS_HIGH_WATERMARK_RATIO=0.8
python -m gemma_tuner.scripts.gemma_preflight
python -m gemma_tuner.scripts.gemma_profiler --model google/gemma-4-E2B
gemma-macos-tuner wizard
# Step 0: Choose "Gemma" family -> LoRA -> gemma-4-e2b (recommended)
# Wizard enforces attn_implementation=eager for Gemma; bf16 preferred on MPS.python -m gemma_tuner.scripts.gemma_tiny_overfit --profile gemma-lora-test --max-samples 32
python tools/eval_gemma_asr.py \
--csv data/datasets/<your_dataset>/validation.csv \
--model google/gemma-4-E2B \
--adapters output/<your_run>/ \
--text-column text \
--limit 200
- Gemma prefers bfloat16. On MPS, we probe bf16; if unavailable we fall back to float32.
- Attention implementation is forced to
eagerfor stability on MPS. - Do not enable
PYTORCH_ENABLE_MPS_FALLBACKin production; it silently moves ops to CPU. - Avoid frequent
.item()calls during training; they force GPU sync and hurt throughput. bitsandbytes/QLoRA are not used on macOS; we use AdamW with gradient accumulation.