We spent most of our build time on the model pipeline and almost none on the review step. That was backwards. Here's what changed after we shipped LyricsGift, a tool that turns someone's story into a finished, custom song.
The naive pipeline
The first version was the obvious one:
story input -> lyric generation -> voice + music synthesis -> MP3
One button, one wait, one result. Technically it worked. Commercially it was a disaster, and the reason had nothing to do with model quality.
Why one-shot generation fails for personal content
Generic content has a wide acceptance window. If you ask a model for a blog intro and it gives you something 80% right, you edit it and move on.
Personal content has almost no acceptance window. A song for someone's late father, or for a wedding first dance, is either right or it is garbage. When the output named the wrong city, or invented a sibling, or hit a cheerful major-key chorus for a memorial, the user did not think "close enough, let me regenerate." They thought "this thing does not understand me."
The failure mode wasn't quality. It was discovering the failure too late. Music synthesis is the expensive, slow, irreversible part of the pipeline. Every bad lyric we sang was compute burned on an output nobody would ever keep.
Splitting the pipeline at the cheap/expensive boundary
The fix was structural, not a better prompt:
story input
-> lyric generation (cheap, fast, editable)
-> USER APPROVES / EDITS <- the gate
-> voice + music synthesis (expensive, slow, final)
-> MP3
Three things fell out of this that we did not anticipate.
1. Cost per delivered song dropped. Regenerations moved from the expensive stage to the cheap one. Users iterate freely on text, then synthesize once.
2. Perceived latency improved even though total time went up. Lyrics appear in seconds, so the user has something real to react to while the slow part runs. The wall-clock time to a finished track is longer than the one-shot version. It feels faster, because the dead time is now filled with a task the user actually wants to do.
3. Attribution of failure changed. Post-gate, if the song is wrong, the lyrics were on screen and approved. That sounds like blame-shifting, but the effect is the opposite: people stopped treating the tool as an unpredictable slot machine, because they could see exactly what it was going to sing before it sang it.
The generalizable rule
If your pipeline has a cheap reversible stage and an expensive irreversible one, put a human checkpoint between them — especially when the output is personal, emotional, or one-shot by nature.
The instinct with generative products is to hide the intermediate representation, because exposing it feels like leaking implementation details. For anything the user has an emotional stake in, the intermediate representation is the interface. Hiding it is the bug.
What we'd do differently
- Build the gate first, then the synthesis. We did it in the opposite order and rewrote the front end twice.
- Make the intermediate representation editable, not just approvable. Read-only approval still leaves people stuck when one line is off.
- Log what users edit. Their edits are the highest-signal eval set you will ever get — they are literally telling you where the model missed, in the exact format the model produced.
If you want to see the shipped version of the flow, it's live at lyricsgift.com — write the story, approve the lyrics, get the track. Happy to answer questions about the pipeline in the comments.
Top comments (0)