Fild's picture
DiffusionGemma tool-selector LoRA + paper (Rud Lord and the KnowledgeOS Agents)
60b165e verified
|
Raw
History Blame Contribute Delete
3.41 kB
# DiffusionGemma QLoRA on Apple Silicon β€” trainer + eval
The first known fine-tuning pipeline for [google/diffusiongemma-26B-A4B-it](https://huggingface.co/google/diffusiongemma-26B-A4B-it)
that runs **entirely on Apple Silicon** via MLX. No diffusion-aware trainer exists in
the MLX ecosystem (`mlx-lm` has no support for the architecture; `mlx-vlm` is
inference-only and its SFT trainer optimizes the wrong, autoregressive objective).
These scripts implement the correct block-diffusion denoising objective.
## Requirements
- Apple Silicon Mac (tested: M2 Max, 64 GB). Training peaks ~17.5 GB with `--grad-checkpoint`.
- `pip install -U "mlx-vlm>=0.6.3" "mlx-lm>=0.31.3" mlx`
- The 4-bit base: `mlx-community/diffusiongemma-26B-A4B-it-4bit` (~15.7 GB).
## Files
| File | What it does |
|---|---|
| `diffusion_lora_train.py` | Block-diffusion QLoRA trainer (the core contribution) |
| `diffusion_eval.py` | Tool-selection benchmark for DiffusionGemma (diffusion generation) |
| `ar_eval.py` | Same benchmark for autoregressive baselines (mlx_lm) β€” fair cross-model comparison |
| `analyze_results.py` | Bootstrap CIs + paired significance + length stratification β†’ report |
| `make_example_data.py` | Generates a synthetic toy dataset (the real corpus is private) |
| `run_chain.sh` | eval β†’ train β†’ eval orchestration with crash-resume |
## 60-second smoke test (synthetic data)
```bash
python3 make_example_data.py --out ./data # 120/24/24 synthetic examples
hf download mlx-community/diffusiongemma-26B-A4B-it-4bit --local-dir ./dg-4bit
# 3 forward/backward sanity iters, then exit
python3 diffusion_lora_train.py --model ./dg-4bit --data ./data \
--adapter-path ./adapters/toy --smoke
```
## Full training
```bash
python3 diffusion_lora_train.py --model ./dg-4bit --data ./data \
--adapter-path ./adapters/toy --steps 250 --grad-checkpoint
```
Key recipe choices (verified against Google JAX / NVIDIA NeMo / Unsloth sources):
**D3PM-uniform corruption** (random vocab tokens, *not* mask tokens), **unweighted CE
over the full 256-token canvas** including supervised EOS-fill, **LoRA r16/Ξ±32** on
attention + dense-MLP (MoE experts/router frozen), **bias-corrected AdamW** 1.5e-4 β†’ cosine.
## Evaluation
```bash
python3 diffusion_eval.py --model ./dg-4bit --adapter ./adapters/toy \
--test ./data/test.jsonl --out ./eval.json
python3 analyze_results.py --dir . # report with CIs + significance
```
## Operational gotchas on Apple Silicon (learned the hard way)
- **Train with `--grad-checkpoint`** β€” faster here than the unchunked backward on this MoE, and ~17.5 GB peak.
- **macOS GPU watchdog** kills long Metal command buffers (`...ImpactingInteractivity`). For *training* use `MLX_MAX_OPS_PER_BUFFER=4 MLX_MAX_MB_PER_BUFFER=20` + the crash-resume loop in `run_chain.sh`.
- **For diffusion EVAL on long prompts** use the Goldilocks `MLX_MAX_OPS_PER_BUFFER=32 MLX_MAX_MB_PER_BUFFER=128`: tiny buffers make long-context prefill crawl; no caps let it trip the watchdog. A per-sample `--sample-timeout` is a backstop.
- **Long-context limitation**: DiffusionGemma is impractically slow to *generate* from ~900-token prompts on MLX today (the encoder prefill), even though *training* is fine β€” a real consideration for agentic use where prompts are long.
## License
Apache-2.0 (matches the base model). Training corpus not included (private).