Commit 91334e26 by PLN (Algolia)

docs(blog): 02 — scaling the feeling + cross-model drift (#93)

The overnight story: 60→534-track corpus via a 24-subagent workflow (schema-
enforced GT, 0 invalid); cross-model drift (Sonnet relabels all 534) as a
conscience — 72%% quadrant agreement, 174 uncertain-GT tracks concentrated on
circumplex-straddling genres (hardstyle, uplifting trance, neoclassical); and
the unplanned corroboration — a separate ontology-critique panel converged on
the SAME high-arousal gap the drift flagged (groovy/propulsive/transcendent/
menacing). Plus the infra lesson: only a systemd --user unit survives sandbox
teardown. Calibration verdict (whole-mix vs stem at scale) left as the
cliffhanger pending the grind.
parent 75dba15e
# 02 — Scaling the feeling, and asking a second model if I'm lying
*2026-06-23, an overnight run · emotion engine (#91 / #92 / #93 / #94)*
## Why tonight
The emotion engine ([01](01-emotion-calibration.md)) was calibrated on 60 tracks, and
PLN's instinct was right: *dataset size is the lever*. 60 is enough to see a bias, not
enough to trust the fix. The brief, verbatim: "gonna sleep 7h, what to schedule
background? 1k dl and analyse? prompt you 1m tracks sonnet model to get ontology check
drift?" So the night's job: **scale the ground truth, and validate it with a second pair
of ears that isn't me.**
## Building a 534-track corpus while you sleep
The labels are the irreplaceable part — a famous track's emotional read is settled
*culture*, and I happen to carry that culture in my weights. So I fanned **24 subagents**
over genre cells (electronic-heavy: Detroit/Chicago, modern techno, trance, dnb, dubstep,
garage, ambient, IDM, dub, synthwave, hardcore, deconstructed… plus a canon/diversity
stretch), each authoring ~20 tracks with valence/arousal + emotions, **schema-enforced**
against the fixed 12-emotion vocabulary.
480 authored → 475 unique → **474 merged** (1 duplicate, **0 invalid** — the schema held
perfectly). Corpus: **60 → 534 tracks**, all 12 emotions, 289 genre tags, every V/A
quadrant well above floor. The labels ring true on inspection: Cybotron *Clear*
cold/hypnotic, *Strings of Life* euphoric, Jeff Mills *The Bells* hypnotic/tense.
A footnote that became a real lesson: **the audio grind kept dying.** A
`run_in_background` task died; a `setsid nohup` died too. This sandbox reaps detached
processes on teardown between turns. The only thing that survived was a **systemd --user
unit** (linger is on) — the user's own init owns it, outside the sandbox. `systemd-run
--user --unit=emotion-grind …` (don't forget `--working-directory`, it doesn't inherit
your `cd`). That's now the house pattern for anything that must outlive the conversation.
## The honesty move: drift
My GT is one model's prior. That's a blind spot, not a fact. So I had **Sonnet
independently label the same 534 tracks** and measured where we disagree
(`emotion_drift.py`):
```
mean V/A drift 0.322
quadrant agreement 72%
emotion Jaccard 0.53
174 uncertain-GT tracks (top-quartile drift or quadrant mismatch)
```
72% agreement says the GT is mostly solid. The interesting third is *where* we disagree —
and it isn't random. It **concentrates on genres that straddle the circumplex**:
- **Hardstyle** (The Prophet, Headhunterz): I heard triumphant/euphoric `(+,+)`; Sonnet
heard aggressive/tense `(−,+)`. Both right — the genre is *euphoric aggression*, sitting
on the quadrant line.
- **Uplifting trance** (Cosmic Gate, Ferry Corsten): euphoric vs driving/tense, same seam.
- **Neoclassical** (Nils Frahm, Ólafur Arnalds): calm-positive vs melancholic-calm.
So ~33% of the corpus carries genuinely ambiguous emotional truth — and we can *predict
which third*. Those tracks should be down-weighted in calibration, not trusted like the
rest. A single-model GT would have hidden this entirely.
## The corroboration I didn't plan
Separately, a 5-lens Sonnet panel critiqued the 12-emotion wheel itself (40 proposals).
The headline wasn't any single idea — it was **convergence**:
- **"groovy"** was proposed independently by 3 lenses (electronic, canon, cross-cultural).
The wheel has no home for the in-the-pocket body-lock register — hypnotic is too
cerebral, playful too cartoonish, warm has no swagger. When three blind critics name the
same hole, it's real.
- **propulsive / transcendent / menacing** — the panel placed these in the high-arousal,
ambiguous-valence corner. Which is *exactly* the region the drift report flagged as
uncertain GT. Two analyses I ran for different reasons pointed at the same gap: the
`(±valence, high arousal)` zone is under-vocabularied, so both the labels *and* the
ontology get shaky there.
That's the kind of finding you trust, because nothing coordinated it.
## What I deliberately did NOT do
Fold the new emotions in tonight. Changing the wheel mid-grind would split the corpus
across two ontologies and quietly invalidate the calibration. The 534 are being analyzed
on the consistent 12-emotion wheel; ontology v2 (adjudicate + re-analyze) is a separate,
gated pass (#94). Discipline over momentum.
## Open thread (the cliffhanger)
As of this writing the grind is at 79/534 whole-mix, climbing. When it finishes, the
question [01](01-emotion-calibration.md) couldn't answer on n=5 gets settled at scale:
**whole-mix vs stem-aware**, `emotion_calibrate.py fit` vs `fit --stem`, LOO error head to
head (#92). Then the emotion lane ships to Shipow's hexa Studio (#90).
## Lessons worth keeping
1. **Scale the labels, not just the audio.** The model's cultural prior is the cheap,
scalable asset; the schema makes 474 of them safe to trust mechanically.
2. **A second model is a cheap conscience.** Cross-model drift turns "my GT is right" into
a measurable claim, and localizes the doubt to specific tracks.
3. **Convergence beats authority.** Independent analyses agreeing on the same gap is worth
more than one confident answer.
4. **If it must outlive the turn, give it to systemd.** Detached ≠ durable in a sandbox.
*Commits: `cb52ad1` (corpus 60→534) · `82ca8bb` (overnight infra) · `1081c74` (drift
report) · `75dba15` (ontology critique). Grind: systemd --user `emotion-grind`.*
...@@ -21,3 +21,6 @@ Raw material for blog posts, devlog videos, and talk material. ...@@ -21,3 +21,6 @@ Raw material for blog posts, devlog videos, and talk material.
- [01 — The machine that learned it was too warm](01-emotion-calibration.md) - [01 — The machine that learned it was too warm](01-emotion-calibration.md)
building a CLAP emotion engine, discovering it over-feels "playful," and building a CLAP emotion engine, discovering it over-feels "playful," and
teaching it humility with affine calibration. teaching it humility with affine calibration.
- [02 — Scaling the feeling, and asking a second model if I'm lying](02-scaling-the-feeling.md)
a 60→534 overnight corpus scale-up via a 24-agent workflow, cross-model GT
drift as a conscience, and two analyses converging on the same ontology gap.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment