DEV Community

"Do Not Duplicate the Character" Duplicated the Character

We built a thing that takes one photo of a child and paints that child into a pre-written 10-page picture book. Thirty books, eleven pages each, on a free image model. Every page has to look like the same kid. Getting from "mostly works" to "every page of every book is clean" took about three weeks, and most of what I learned contradicted what I thought I knew about prompting. Here are the parts that generalize. The headline finding At one point we had a page - a doctor's office scene - that kept rendering two children and two doctors. Standard debugging instinct: be more explicit. So the prompt grew: EXACTLY ONE child the child appears only once, never duplicated do not add a second doctor - โ€ฆplus a verbatim re-description of every character, their positions, the art style, the composition Final prompt: 1,924 characters, with some version of "do not duplicate" appearing seven times. Result: two children, two doctors. Then we cut the whole thing down to one sentence: Add the child from the first image into the second image, . Clean. First try. We reproduced this on a second page from a different book with the same outcome. The mechanism, as far as we can tell: Mention-is-summon applies to duplication itself. Every time you write "do not duplicate," you put another instance of the subject into the context. The model is not parsing your negation; it is being handed the noun again. This is the same reason no other moon in a prompt produces a second moon, and no second kitten produces a second kitten. We hit both. Negation doesn't subtract - it just mentions. The rule we ended up with: to suppress something, never name it. Not even to forbid it. The state-level version, which is nastier "Mention is summon" is well known for objects. It also applies to states, and that one cost us a day. We had a page that needed a collapsed sandcastle. The scene description literally said a sandcastle collapsing into a heap . The model painted an intact, perfect sandcastle. Every time. We tried knocked down , broken heap , towers toppled . All produced pristine sandcastles. What worked was refusing to say the word at all: a big flattened mound of damp sand where something was built and then squashed, one broken turret fragment lying on its side 3/3 clean. The noun sandcastle summons the canonical form of a sandcastle, and adjectives are far too weak to overcome that. If you want a non-canonical state - broken, empty, collapsed, abandoned - describe the state without ever naming the object. Commas make extra bodies This one is stupid and mechanical and cost us more pages than anything else. Our per-page prompts have an action field. Actions written with commas: kneeling by the pond, holding a jar, looking up โ€ฆget read as parallel subjects, and you get two or three bodies performing them separately. One sentence, zero commas: kneeling by the pond and holding a jar while looking up When we finally audited the library, 269 out of 310 pages had commas in the action field. We had only noticed on the ~39 pages that were failing loudly enough to investigate. The rest were quietly carrying the same risk and we had never tested them. Worth internalizing: the pages that fail visibly are a sample, not the population. Position anchors: unique, or the model builds two Two related failures, and the fix for one is the cause of the other. No position at all is the worst case. If you describe a prop centered in frame with symmetric empty space on both sides, the model resolves the ambiguity by putting one on each side. We hit this on multiple pages; it looks like a "duplication bug" and it isn't - it's composition. A non-unique anchor is nearly as bad. at the right of the shelf , on a page where the shelf runs the full width, fails. directly beneath the model ship - where there is exactly one model ship - works. And the two fixes are not independent. On one page, removing commas alone gave 0/4 clean. Adding an anchor alone gave 3/4 duplicated. Both together: clean. On another page the pattern was reversed. We stopped trying to isolate them and just applied both everywhere. When the prompt is not the problem The most useful heuristic we developed: If six blind re-rolls of the same prompt can't produce one clean image, stop re-rolling and stop rewriting words. Go look at the base image. The canonical case: a page whose background art had the main subject filling the entire frame. There was nowhere for a person to stand. Six different prompt rewrites ร— two base images = 22 duplicated results out of 25. We regenerated the background - wider shot, subject pushed to one side, deliberate empty ground on the other - and the same prompt went 3/3 clean immediately. Composition problems masquerade as prompt problems. Sampling harder just buys you more expensive failures. Architecture: never reference the source photo per page The part that actually made cross-page consistency work is structural, not textual. The naive approach is to pass the child's photo as a reference on every page. Don't. Real user photos are hostile input - hair over the face, three-quarter angles, motion blur, other people in frame - and every page inherits that noise independently, so the kid drifts. Two stages instead: uploaded photo โ†’ ONE canonical character sheet (clean front-facing full body, book art style, fixed outfit) โ†’ per page: image-to-image with refs = [character sheet, blank page art] Every page anchors to the same canonical image. Messy input gets normalized exactly once, in a step where you can inspect the result before spending eleven more generations. Cross-page consistency went from "usually" to "reliably." Two supporting tricks: Fixed costume as an identity anchor. The character's outfit is written verbatim into every page's identity clause and never changes. Pose and expression are the variables; the costume is the constant. If you're designing the source material yourself, give the protagonist one outfit for the whole book. (Watch the edge cases - we shipped a bedtime page where the kid slept in a raincoat, because the costume rule outranked common sense.) Supporting characters live in the prompt, not the base image. Image-to-image on these models is a full repaint, not a local edit, so "keep the teacher exactly as she is" always fails - she drifts or gets replaced. The fix is a per-page cast string describing each supporting character, injected into the generation prompt. Then they get repainted back into the same person. Two API-level things that cost real time Reference images were being silently dropped. Our provider has an OpenAI-compatible endpoint that ignores unknown top-level fields. We were sending image at the top level; it needed to be inside extra_body . No error, no warning - every "image-to-image" call was quietly running as pure text-to-image, in production, for weeks. Character consistency on the free tier had been running on the text description alone. The tell was in the response: output URLs contained /images/t2i/ instead of /images/i2i/ . If your provider gives you any observable signal like that, assert on it in a test. POST /v1/images/generations { "model": "...", "prompt": "...", "size": "1024x768", "extra_body": { "image": [" "], "response_format": "url" } } Also: pass references as base64, not URLs. A hosted URL that expires or blips takes the whole job down, and it makes resuming a long batch depend on that URL still being alive. Text-to-image and image-to-image can fail independently. We spent an afternoon on what looked like a total outage. Same key, same model: t2i returned 200 in 14 seconds while i2i silently hung on every request regardless of reference or size. Not a 503, not a queue-full - just nothing. If you have both paths, health-check both. QA: partial verification lies Last one, and it's a process lesson rather than a technical one. We reviewed in rounds, and each round only re-checked the pages that had been regenerated in that round. Completion looked like ~95%. Then we did one strict pass over every page of every book, and immediately found problems in pages that had been marked PASS rounds earlier: a bike that still had training wheels after the story said they came off, a duplicated object on a cover, one page that had never generated at all. Incremental QA over a generative pipeline accumulates false confidence, because "this page was fine last week" is a claim about a sample from a distribution, not about a build artifact. Re-verify the whole thing before shipping. The short version - Never name what you want suppressed - negation summons. - To get a non-canonical state, describe the state and never say the noun. - One sentence, no commas, in action descriptions. - Anchor positions to something unique; no anchor is worse than a bad one. - If K=6 re-rolls all fail, the base image or the composition is wrong, not the wording. - Normalize identity once into a canonical reference; anchor every page to that. - Assert that your reference images actually arrived. - Re-QA everything before shipping, not just what you touched. Most of these reduce to the same underlying fact: the model is not following your instructions, it is conditioning on your tokens. Every token you add is a vote for what appears. "Don't" is not a strong enough word to reverse a vote. I build Doodara, a free AI storybook maker for kids - the template books described here are live if you want to see the output. Happy to answer questions about the pipeline in the comments. Top comments (0)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.