Ray Swan_

LoRA Workbench

2026 · Platform · Architect, Engineer & Technical Product Lead

Standardized, auditable fine-tuning — declarative playbook, gated MLflow registry, full provenance on a 4GB T1000 — so the small model you ship is the model you can prove.

01 · Problem

The constraint

Small-model fine-tuning collapses when every run invents its own data, thresholds, and lineage. The LoRA workbench had to make the adapter auditable — one trainer.py, one playbook, every promotion gated — and prove it on a 4GB Quadro T1000 without pretending the lab is the cloud.

02 · Built

What shipped

Built a governed micro-factory: Qwen2-0.5B-Instruct + PEFT LoRA (r=4) under MLflow hermes/llm-lora isolation (batch2 eff8, seq 64/32/128, BF16). corpus25_playbook.yaml declares SST-2, 4-way intent, and 16-tag BCE, with thresholds ln4→1.5 and BCE 0.693→0.48. One trainer.py routes CE to BCE via task head; corpus25_playbook is the only change. Optuna parent run + child trials, disk + Hub lineage, and assert_promotable(val/loss ≤ threshold) before any registry promotion.

03 · Decisions

The path

  1. 01
    Not Axolotl, not LlamaFactory — the plumbing they skip

    Axolotl and LlamaFactory solve math and speed. Neither solves discipline: experiment tracking, a quality gate before registry, or a way to jump domains without new code. This factory is the mini-CI/CD for adapter weights that small teams otherwise rebuild by hand with shell scripts and checkpoint-500 folders.

  2. 02
    Probe on 4GB (200/40 @64)

    Proved the loop on a Quadro T1000 before claiming it works.

  3. 03
    Intent 24→200 proves both sides of the gate

    Showed the gate blocks and the gate passes — same code, different data.

  4. 04
    Tags 60→180 → 5ep earns 0.48 honestly

    No threshold hacking. Valid loss 0.464 is the receipt.

  5. 05
    Disk, Hub, and playbook lock

    Every adapter has a lineage you can re-run from the playbook, not a notebook you have to believe.

04 · Architecture

How it is built

Declarative playbook

corpus25_playbook.yaml declares datasets (SST-2, 4-way intent, 16-tag BCE), thresholds (ln4→1.5, BCE 0.693→0.48), and stages; trainer.py stays untouched.

Gated registry

assert_promotable(val/loss ≤ threshold) — nothing registers that didn't earn it. Optuna parent 919de78a + child trials under hermes/llm-lora.

4GB guardrails

seq 64 (32 intent, 128 tags), batch 2 eff 8, r=4 — the heavier regularizer that beats r=8 on 200 rows. BF16 with GradScaler auto-disabled, pad_token_id pinned at 151643, datasets pinned at 2.21.0, and TMPDIR moved off a 16G tmpfs so 1G model.pt saves don't blow the disk. Proved on a 4GB Quadro T1000, not a rented A100.

Parent/child lineage

Optuna sweep parent run + child trials, disk + Hub, playbook digest — every adapter is provenance-complete.

CE→BCE without code change

One trainer.py routes binary CE to 16-head BCE via head config. Playbook is the variant, not the code.

05 · Surfaces

What it looks like to operate

Governed lineage
Plate
Governed lineage

Playbook → trainer → MLflow gated registry → Hub. One factory, every adapter auditable.

06 · Standing

What this proves

Proves: I can ship auditable fine-tuning — one trainer, one playbook, every adapter gated and lineaged.

Three registered stages prove the manifest routes across domains without touching trainer.py: v3 binary CE 0.5804 on SST-2 (a14e623b, main HEAD), v5 4-way intent CE 1.44 / 54%, and v6 16-head BCE 0.464 / 80.5% Hamming (f1cd0b43, v6-narrative-tags). Optuna parent 919de78a best 0.5804 (trial 004, r=4 beats r=8). Local 4GB proof that a declarative, gated factory works — the same discipline the Factory applies at platform scale.

Governed LoRA factory: declarative playbook, gated MLflow registry, 4GB guardrails, parent/child lineage, disk+Hub provenance.

01 / 06 · Problem