We are building an AI Story App called Sutori Chat, with ~3.7k users. To improve engagement and retention we needed capabilities that neither open source nor closed models gave us, so we trained our own. This is what happened, including the parts that did not work.
- SFT
- Supervised fine-tuning. Show a model 3,000 strong examples and train it to reproduce their style.5
- Comparison
- One story prompt, two responses, and a label for the better response. This is the training unit for our judge.
- Reward model
- A second model that reads two responses and decides which is better. In effect, a judge.
- GRPO
- A reinforcement-learning method. The writer generates several responses, the judge ranks them, and the writer learns from the winners. Then the cycle repeats.6
The problem
Text
Frontier models write stories with proper structure and grammar, but they do not make engaging stories people come back to. We used our user data and asked an AI judge to compare responses (A vs. B). The judge preferred the wrong response 65% of the time.
Images
Open source and closed models are good at very specific art styles, but our users wanted the aesthetics you see on Pinterest or Cosmos.so. Prompting was not enough to get that look.
Part one · text
Lotus-1
We started with Qwen/Qwen3.6-35B-A3B2, a 35B-parameter model with roughly 3B active at any time. The recipe is Meta's CharacterFlywheel:1 SFT, then a reward model, then GRPO. Everything is trained with LoRA rather than full fine-tuning, which at this data scale costs nothing in quality.4
The training data is a proprietary set of 3,000 comparisons across 338 story prompts (each one a prompt, two responses, and a label saying which is better).
Step 1: SFT matches the target
SFT got us very close to the reference style. Judged by our first reward model, it beat real reference responses 48.6% of the time (a coin flip, which is exactly the target for an imitation stage).
Three style markers. The dashed line is our target; closer is better. Each panel has its own vertical scale, so the ratio at the end of each run is labelled.
Step 2: the first reward model was measuring the wrong thing
While training, we realized the judge scored 99.9%. Every pair of responses came from two different models, so the judge could win just by figuring out which model wrote the response, based on length, punctuation, and line breaks. A simple model using only those signals matched the judge almost exactly. We needed a judge that actually reads for quality, not one that reads length, punctuation, or line breaks.
Each row is a version of the dataset. The ring is a 12-feature probe that only counts length, punctuation, and line breaks. On raw and restyled it lands almost exactly on top of the reward model. That overlap is the finding: the judge is doing nothing more than the probe.
Step 3: GRPO immediately reward-hacks a flawed judge
When we trained GRPO against that judge, it reached a 100% win rate, far beyond the 65% ceiling that signals reward hacking. It also stopped writing in full sentences.
Scored by the first (broken) reward model. Step 4 rescores everything with the rebuilt judge, and the numbers move.
Same prompt, both versions from this run:
Alex shifts in his seat, pen tapping nervously against his notebook. He keeps glancing at your test—close enough to see the answers without leaning over.
His jaw tightens. She didn't even look at me.
The teacher calls out: "Five minutes left!"
He scribbles something on a scrap of paper and subtly slides it toward you with two fingers—unfolding it just enough that only you can read: "You knew all this? Why didn't you tell me?"
she
The teacher drops the first test paper.
Alex's pen snaps.
He doesn't look at you. Doesn't breathe right.
But his hand—white-knuckled around his pencil—twitches once.
Like a reflex.
Like pain.
And when he finally lifts his eyes to scan the room…
They don't find yours.
Every line is its own paragraph, and it starts with the word "she". The model found the judge's blind spot: the judge slightly preferred line breaks and ellipses, so that is almost all the model produced. This run was a failed experiment.
Step 4: a real judge, and the step we shipped
We rebuilt the reward model, and it scored 70.1%, which is what a real judge should score.1 We ran GRPO again and checked every step of training. The automated checks rejected every step, including step 10. So we read the outputs ourselves, and we preferred step 10's responses a lot more. Same prompt, both versions:
Alex shifts in his seat beside you, tapping his pencil once—twice—like he's trying to look casual. He glances at your test paper, then away fast, jaw tight.
His eyes flicker with something sharp beneath the charm: a quiet sting of being ignored.
He clears his throat softly and turns back to his own exam, pretending not to care—but every so often, his gaze drifts toward yours again.
Alex slams his pencil down hard enough to snap it in half. He watches you turn the page—calm, focused, too good.
His jaw tightens.
The teacher calls out: "Two minutes left."
Alex glances at your test paper again. Every answer is correct. Even the bonus question? You nailed it without hesitation.
He hates this.
Hates how easy you look now—like nothing ever went wrong between you two back in high school when he was perfect and you weren't even trying… but still smarter than him somehow.
What it cost
Part two · image
Krea 2 Dream-1
We started with Krea 2 Turbo3, a 12.9B model. On top of it we trained 111 LoRA adapters, covering more than 20 distinct art styles, for $384 total. A typical run is about 30 images and 800 steps: roughly $2.34 and 12 minutes per adapter.
What it makes
Here are 5 example art styles from the model:
Captioning was the hardest part
An adapter learns whatever its captions say the images have in common. Get that wrong and the adapter locks onto the wrong thing (the pose, the background, the crop), and no prompt will fix it later. So we caption every image with Muse Spark 1.1 and judge what comes out.
In our past experiments we realized that Muse Spark 1.1 is the best model for image captioning.
What we learned
- A judge that is nearly always right is not a judge. 99.9% meant ours had found a shortcut (it was identifying the author, not the better answer). A simple model that only counts punctuation matched it almost exactly, which is an example of reward hacking. The judge was not preferring responses based on the writing itself.
- Build the judge the way we actually train. Our first judge compared two unrelated generators, so all it learned was telling the generators apart. When we rebuilt it to compare the reference against our own output, the score dropped from 99.9% to a believable 70.1%.
What we could not do
- No safety alignment. That requires paid human annotators. This work measures capabilities only. It is not a safety result and should not be read as one.
- No objective image evaluation. We rated every image by eye ourselves, but we do not have human annotators who can judge the outputs objectively.
- No flywheel. CharacterFlywheel runs 15 training generations.1 We ran one. Every additional loop costs money we have not raised.
- Not enough labeled data. 3,000 comparisons built the judge, and that number should be an order of magnitude larger. We would like to work with data vendors to get there.
What's next
Next, we want to train the image model directly with preference optimization instead of stacking LoRAs on someone else's checkpoint. Adapters do not learn from the users who see them. A real flywheel needs a model that does.
We plan to release this work openly. If you work on reward modeling or image post-training, we would like to talk, mostly about compute. We have ~3.7k users producing real data, a labeled preference set, a pipeline that works end to end, and a clear record of what breaks. What we do not have is the budget to run it more than once.
References
- 1 CharacterFlywheel: Scaling Iterative Improvement of Engaging and Steerable LLMs in Production. Meta AI Research, March 2026. arXiv:2603.01973. The source for the SFT → reward model → RL recipe, the 65% win-rate ceiling (60% ideal), the 15-generation flywheel, and the accuracy range real preference models actually occupy (roughly 50–75% on human-labeled pairs).
- 2 Qwen3 Technical Report. Qwen Team, Alibaba, May 2025. arXiv:2505.09388. Qwen3.6-35B-A3B is the writing policy; Qwen3-8B backs the first reward model and Qwen3.5-9B the retention model. This report covers the Qwen3 generation only (neither Qwen3.5 nor Qwen3.6 has a published report of its own, so parameter counts and architecture claims for those two come from their model cards, not from this citation).
- 3 Krea 2 Technical Report. Krea AI, June 2026. krea.ai/blog/krea-2-technical-report. The 12.9B open-weights diffusion transformer underlying all 111 adapters. We use K2 Turbo, its distilled checkpoint.
- 4 LoRA Without Regret. Thinking Machines Lab, September 2025. thinkingmachines.ai/blog/lora. The basis for training everything with LoRA instead of full fine-tuning: at datasets this size, a sufficiently high-rank adapter applied to every layer matches full fine-tuning, and RL needs far less capacity than supervised training does.
- 5 Training Language Models to Follow Instructions with Human Feedback. Ouyang et al., OpenAI, March 2022. arXiv:2203.02155. The InstructGPT paper, and the origin of the supervised fine-tuning step as we use it: fine-tune on a small set of high-quality demonstrations first, then collect rankings and train a reward model on top. Our 3,000-example SFT stage is the same move at a smaller scale.
- 6 DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models. Shao et al., DeepSeek-AI, February 2024. arXiv:2402.03300. Introduces Group Relative Policy Optimization. GRPO drops PPO's separate value network and instead scores a group of sampled responses against each other, which is why it fits a setup like ours where the reward model is the only critic and memory is the binding constraint.
