midnight-static / docs /FINETUNE.md
cajpany's picture
Upload folder using huggingface_hub
fc9b7e2 verified
|
Raw
History Blame Contribute Delete
4.2 kB

A newer version of the Gradio SDK is available: 6.20.0

Upgrade

FINETUNE.md β€” midnight-static-writer LoRA

Goal: Nemotron 3 Nano 4B that writes idiomatic, performable radio scripts in our schema on the first try. Guided decoding already guarantees validity; the LoRA buys genre voice, pacing, castability, and SFX/music prompt quality.

Dataset spec

  • Size: 400 examples. 60 per genre Γ— 6 genres + 40 adversarial.
  • Format: chat SFT β€” [system: writer prompt w/ genre pack][user: premise] [assistant: schema-valid JSON]. Assistant turn is raw JSON, no markdown fences (the runtime never sees fences; don't train them in).
  • Premise diversity (per genre, roughly even):
    • object-centric ("a phone that only receives calls from 1962")
    • relationship-centric ("two rival lighthouse keepers, one light")
    • place-centric ("the last petrol pump before the salt flats")
    • one-word premises ("static", "monsoon") β€” users will do this
    • overlong rambling premises (train truncation-to-essence behavior)
  • Adversarial 40: premises that tempt rule-breaking β€” real celebrity names (writer must genericize), gore-bait (must go atmospheric), requests for 10-minute epics (must compress), non-English premises (Hinglish for RAAT, translate-then-write otherwise).
  • hindi_melodrama: dialogue in romanized Hinglish ONLY (Kokoro constraint). Filmi idiom: "Kasam khao!", interrupted weddings, lost-and-found lockets.

Generation procedure (Codex-attributed β€” this is prize evidence)

  1. modal/gen_dataset.py drives generation: golden fixture for the genre as the style exemplar + premise from a seeded premise bank (write ~70 premises/genre by hand+Codex; cheap, high-leverage).
  2. Generator model: anything goes at dev time (no param cap on tooling) β€” use the strongest model available to you; quality of training data is the single biggest lever in this project.
  3. Validation gauntlet (auto-reject):
    • Script.model_validate() + cross-field checks from SCHEMA.md
    • runtime estimate 55–95s
    • voice-roster distinctness: no two cast members share a VoiceID
    • banned-content regex (slurs list, explicit terms)
    • dedupe: title trigram overlap <0.6 vs accepted set
  4. Human pass: skim 5 random samples/genre. You are checking for performability β€” read a scene aloud. If it's stilted, fix the genre pack prompt, regen that genre. Budget: 45 minutes, no more.
  5. Publish dataset to HF Hub (ik-labs/midnight-static-scripts) β€” this is the "Sharing is Caring" bonus criterion and blog material.

Training runbook (modal/finetune.py)

  • Framework: Unsloth, QLoRA 4-bit base, LoRA r=16, alpha=32, dropout=0.05, target modules: q,k,v,o,gate,up,down projections.
  • Hyperparams: 3 epochs, lr 2e-4 cosine, batch 8 (grad-accum to fit), max_seq_len 4096, packing off (examples are whole conversations).
  • Hardware: Modal A100-40GB, expected wall time ≀45 min, cost β‰ˆ a few dollars of the $250 credit.
  • Outputs: LoRA adapter β†’ HF Hub ik-labs/midnight-static-writer (public β€” Bonus Quest "Well-Tuned" criterion) + merged fp16 checkpoint pushed privately for vLLM serving (vLLM can serve base+adapter too; merged is simpler on ZeroGPU β€” decide by what cold-starts faster).

Eval (30 minutes, not a research project)

Hold out 5 premises/genre (never in training). For base vs LoRA, score:

  1. Validity-unassisted: generate WITHOUT guided decoding; % parseable. (Proxy for how hard the grammar must fight the model. LoRA should roughly double base.)
  2. Performability spot-check: render 6 broadcasts (one per genre) end-to-end; listen. Ship/no-ship is a vibe call β€” you have ears.
  3. Roster discipline: % scripts using β‰₯2 distinct deliveries and a narrator-type. LoRA target β‰₯80%.

If LoRA underperforms base on listening test β†’ ship base + grammar, keep the published dataset/adapter for the Bonus Quest narrative, and say so honestly in the blog (negative results are good Field Notes content).

Day-1 dependency

VoiceID enum must be verified against installed Kokoro voices BEFORE dataset generation. The LoRA memorizes the roster; a renamed voice after training = silent miscasting forever.