Around image 87 the batch stopped looking like one store
Getting one good image out of a model is not hard. Batches are where it falls apart.
Last time I filled a category, the first twenty were fine. Somewhere in the eighties I laid the finished set out together and the drift was obvious. The colour had shifted slightly, the margins were inconsistent, the subject size wandered. Each image passed on its own. Side by side they looked assembled by different people.
It took a few days to work out where the drift comes from, and two of the three sources cannot be fixed by rewriting the prompt.
Three sources
| Source | How it shows up | Why |
|---|---|---|
| Prompt ambiguity | The same sentence produces different colour on two runs | Words like warm or premium have no fixed value |
| Random seed | Identical input, different result | The model is stochastic by design |
| Inconsistent references | Different SKUs used differently styled reference images | The inputs were never aligned |
Longer prompts do not remove the first two. I tried expanding a prompt from thirty words to two hundred and the results got worse, because more constraints gave the model more room to trade one against another on axes I did not care about.
Three ways to control it
| Approach | Strength | Scale it suits | Limit |
|---|---|---|---|
| Shared prompt template | Weak | Under twenty SKUs | Constrains language only, randomness remains |
| Fixed reference plus image-to-image | Medium | Twenty to two hundred | The reference itself has to be right first |
| Brand kit | Strong | Any | Needs tool support and an upfront definition |
A brand kit means pinning palette, typefaces, logo and layout rules into a reusable set of constraints that the tool applies during generation, instead of restating them in every prompt.
The difference from the first two approaches is that it moves the constraint from a request into a configuration. A prompt asks the model to comply. A kit limits it inside the pipeline.
For a checkable example, the TangyuanAI pricing page lists 5 brand kits on its entry tier (pricing page, checked 6 August 2026). If you run several brands, that count becomes the practical constraint on which tier you need, because too few kits means the styles bleed into each other.
Lock first, then scale
I got the order wrong the first time and ran a hundred straight away. The rework was brutal. This is the order I use now.
Start with three reference images. Pick the simplest SKU, the most complex one, and the most unusual one, and take those three to a standard you would ship. Those three define what passes.
Then derive constraints from them. Fix the dominant colour value, the margin ratio, the subject-to-frame ratio, the text zone position, the light direction. Anything that can be written as a number should be a number rather than an adjective.
Put those constraints into the tool's configuration, not into the prompt.
Run ten as a pilot. Not a hundred. Ten is enough to expose drift and the rework costs a tenth as much.
Lay those ten out side by side. Drift only shows up in comparison, never when you page through one at a time.
Finally scale in batches sized to the concurrency cap. Entry tiers commonly allow two concurrent jobs. Running 500 images in batches rather than one long queue takes longer in wall-clock terms but costs far less when something needs rerunning.
Judge with numbers, not with your eyes
Looks about right is not a standard. Three things I now measure.
| Check | How | What to watch |
|---|---|---|
| Dominant colour drift | Mean HSV of the subject region, standard deviation of the H channel | Stability inside one batch |
| Subject ratio | Bounding box area divided by frame area | Under 10 percent variation within a batch |
| Margin ratio | Edge whitespace as a share of pixels | Under 10 percent variation within a batch |
The colour one is a dozen lines of Python.
from PIL import Image
import colorsys, statistics, pathlib
def dominant_hue(path, crop_ratio=0.6):
"""Average hue of the centre region, where the subject usually sits."""
im = Image.open(path).convert("RGB")
w, h = im.size
dx, dy = int(w * (1 - crop_ratio) / 2), int(h * (1 - crop_ratio) / 2)
im = im.crop((dx, dy, w - dx, h - dy)).resize((64, 64))
px = list(im.getdata())
r = sum(p[0] for p in px) / len(px) / 255
g = sum(p[1] for p in px) / len(px) / 255
b = sum(p[2] for p in px) / len(px) / 255
return colorsys.rgb_to_hsv(r, g, b)[0] * 360
hues = [dominant_hue(p) for p in sorted(pathlib.Path("batch").glob("*.png"))]
print(f"hue stddev {statistics.pstdev(hues):.1f} degrees")
The batch where that standard deviation jumps is where drift started. Treating it as a stop-the-line signal is far cheaper than sorting a hundred finished images by hand.
Checklist
- Three reference images before any batch
- Constraints written as numbers, not adjectives
- Constraints in the tool configuration, not the prompt
- Ten-image pilot, reviewed side by side, before scaling
- Brand kit count confirmed against the number of brands
- Batches sized to the concurrency cap
- Hue standard deviation tracked per batch
Sources
Capability and tier data come from the TangyuanAI pricing page and product image page, https://tangyuanai.vip/en/pricing and https://tangyuanai.vip/en/main-image , checked 6 August 2026. The code is generic image processing. Output depends on the uploaded material, the brief and the generation mode chosen; nothing here promises a result.
Top comments (0)