<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Merl Merl</title>
    <description>The latest articles on DEV Community by Merl Merl (@merl985).</description>
    <link>https://dev.to/merl985</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4028925%2F309a350a-b9f4-41fb-b074-88d8a67eb019.png</url>
      <title>DEV Community: Merl Merl</title>
      <link>https://dev.to/merl985</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/merl985"/>
    <language>en</language>
    <item>
      <title>I Scoped an AI Edit to Panel 1 and Got a Diff in Panel 4</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Thu, 08 Oct 2026 20:19:03 +0000</pubDate>
      <link>https://dev.to/merl985/i-scoped-an-ai-edit-to-panel-1-and-got-a-diff-in-panel-4-2djp</link>
      <guid>https://dev.to/merl985/i-scoped-an-ai-edit-to-panel-1-and-got-a-diff-in-panel-4-2djp</guid>
      <description>&lt;p&gt;I wanted to know how well an AI model handles a full manga page as one unit: four panels, two speakers, and two short lines of dialogue that belong in specific bubbles. So I wrote the page as a spec and generated it with Tsubaki.3 on PixAI. Then I patched it through a chain of edits in PixAI Studio and checked each output the way I would check a diff.&lt;/p&gt;

&lt;p&gt;In the first run, most of my assertions passed. The edits were where I found side effects outside the declared scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fixture
&lt;/h2&gt;

&lt;p&gt;The test page is a karaoke grudge match between two characters with deliberately different silhouettes, so a swapped identity or a misattributed line would be visible at thumbnail size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;black-and-white manga, ink lines, screentone&lt;/span&gt;
  &lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;wide&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;half + half&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;wide&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;reading_order&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;left-to-right, top-to-bottom&lt;/span&gt;
&lt;span class="na"&gt;characters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;genzo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;short and round&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;hair&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;tall white pompadour&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;fumiko&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;tall and thin&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;hair&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;high bun&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;glasses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;span class="na"&gt;panels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;shot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;wide&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;     &lt;span class="nv"&gt;speaker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;fumiko&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BEAT&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;98,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;OLD&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;MAN."&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;screen&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;blank&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;shot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;close-up&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;speaker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;none&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;shot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;low angle&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;speaker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;none&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;shot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;medium&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;   &lt;span class="nv"&gt;speaker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;genzo&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;  &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;TURN."&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;        &lt;span class="nv"&gt;screen&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100"&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real prompt was plain English, one paragraph for the page rules, one for each character, then one numbered paragraph per panel. The YAML above is only the structure I tested against. Each panel differs from the previous one in exactly one variable (shot, action, or speaker), so I could check each assertion on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  First run: four versions, eight assertions
&lt;/h2&gt;

&lt;p&gt;I generated four versions in one batch with Prompt Helper off, so the model received the prompt unchanged. Then I checked each version at three to four times its size.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assertion&lt;/th&gt;
&lt;th&gt;Pass rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Four panels in the declared layout&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Panel order matches the spec&lt;/td&gt;
&lt;td&gt;3/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Both lines spelled exactly&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Panel 1 tail aimed at Fumiko&lt;/td&gt;
&lt;td&gt;0/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Panel 4 tail aimed at Genzo&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Panel 1 screen blank&lt;/td&gt;
&lt;td&gt;0/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Panel 4 screen shows 100&lt;/td&gt;
&lt;td&gt;3/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fumiko's cup tipped over in Panel 4&lt;/td&gt;
&lt;td&gt;3/4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq1vh7b7n0awj823bfupo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq1vh7b7n0awj823bfupo.jpg" alt="Panel 1 from four versions, each speech bubble tail aimed at the singer instead of the woman at the table" width="799" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two failing rows are both in Panel 1. In every version the text was correct, the bubble was clean, and the speaker was wrong. The model also put an unrequested score on the screen: 190 once, 100 twice, and "10 0" once. With a 100 in Panel 1, the reader knows the result of Panel 4 in advance.&lt;/p&gt;

&lt;p&gt;I picked the version with the cleanest Panel 4 as the base for editing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnk7tlfu59uqzfsvv37ug.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnk7tlfu59uqzfsvv37ug.jpg" alt="The first generated four-panel manga page, with the Panel 1 bubble beside the singer and a score of 190 on the screen" width="800" height="1079"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Patching in PixAI Studio
&lt;/h2&gt;

&lt;p&gt;In PixAI Studio, every step is a node on a canvas, wired to the image it takes as input. Each edit was a new Tsubaki.3 node with one output. Every instruction had two parts: the change, scoped to one panel, and a keep list naming what must stay the same.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node&lt;/th&gt;
&lt;th&gt;Intended change&lt;/th&gt;
&lt;th&gt;Change made&lt;/th&gt;
&lt;th&gt;Side effects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Panel 2: new expression&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;Genzo gained glasses like Fumiko's&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Panel 3: two background customers&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;Panel 1 face and lettering changed, page shrank&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4 (from 2)&lt;/td&gt;
&lt;td&gt;Panel 2: remove the glasses&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;Fumiko's Panel 1 expression changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Panel 1: move bubble, blank screen&lt;/td&gt;
&lt;td&gt;bubble yes, screen no&lt;/td&gt;
&lt;td&gt;Panel 4 screen cleared, Panel 1 screen removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Panel 4: restore the 100&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;both teacups changed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I dropped Node 3 and branched again from Node 2, so the final page is the output of the path 1, 2, 4, 5, 6.&lt;/p&gt;

&lt;p&gt;I learned the most from Node 5, where I scoped both changes to Panel 1 and named the 100 in Panel 4 in the keep list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In Panel 1 only, make two changes. Move the speech bubble that reads
"BEAT 98, OLD MAN." to the upper left of the panel, above Fumiko ...
Make the score screen on the wall dark and blank ...
Keep Panel 2, Panel 3 and Panel 4 exactly as they are, including ...
the number 100 on the score screen in Panel 4 ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model moved the bubble as asked. For the screen, it ignored the panel scope: it removed the one in Panel 1 and emptied the one in Panel 4, although the keep list named the 100 explicitly. From the outside, this looked like a selector that matched every object of the same type on the page instead of the one inside the declared panel. That is an analogy for what I observed, not a claim about how the model works internally.&lt;/p&gt;

&lt;p&gt;In Node 6, the model restored the 100 and also edited two other repeated objects: Fumiko's teacup in Panel 1 now floats above a tilted saucer, and a second cup appeared in Panel 4.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fts0vjcmog00ch7qzfrim.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fts0vjcmog00ch7qzfrim.jpg" alt="Panel 1 and Panel 4 after Nodes 4, 5 and 6, showing the bubble moving to Fumiko, the Panel 4 screen going blank, and the 100 returning with changed teacups" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would put in a checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Run a batch and assert per panel. With a single version, I could not have seen that the speaker error appeared in all four.&lt;/li&gt;
&lt;li&gt;Treat speaker assignment as its own assertion. A line can be spelled correctly and still be in the wrong character's bubble.&lt;/li&gt;
&lt;li&gt;Give a bubble a position on the page, together with the speaker's description. In my one run of this fix, the model moved it to the right character.&lt;/li&gt;
&lt;li&gt;Diff the whole page after every edit, including panels outside the scope. In this test, the model changed Fumiko's face, the score screen, and the teacups in panels outside the target.&lt;/li&gt;
&lt;li&gt;Branch when an edit fails. If I had continued from Node 3, its unrequested changes would have been in every later step.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Untested idea for the next run: when an object appears in several panels, address the target by its position on the page as well as by its panel number.&lt;/p&gt;

&lt;p&gt;The finished page is readable from top to bottom, and I kept the two teacup changes on it as evidence. If you want to run the same experiment on your own four-beat scene, you can &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;try it on PixAI&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>Integration-Testing an Anime Character on Tensor.Art and PixAI</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Mon, 28 Sep 2026 11:07:02 +0000</pubDate>
      <link>https://dev.to/merl985/integration-testing-an-anime-character-on-tensorart-and-pixai-3c5f</link>
      <guid>https://dev.to/merl985/integration-testing-an-anime-character-on-tensorart-and-pixai-3c5f</guid>
      <description>&lt;p&gt;A single good anime image is a unit test. A character you want to reuse is an integration test: the same spec has to pass after generation, after a structured layout, and after two edits in a row. I ran that integration test on Tensor.Art and on PixAI with &lt;a href="https://eap.pixai.art/go/balazs2" rel="noopener noreferrer"&gt;Tsubaki.3&lt;/a&gt;, PixAI's newly launched anime model, and logged every assertion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;PixAI&lt;/th&gt;
&lt;th&gt;Tensor.Art&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Generation&lt;/td&gt;
&lt;td&gt;Tsubaki.3, Prompt Helper off&lt;/td&gt;
&lt;td&gt;WAI-illustrious v17 checkpoint, platform defaults&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reference&lt;/td&gt;
&lt;td&gt;image in the prompt box (&lt;code&gt;@image1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;IP-Adapter (ControlNet)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edits&lt;/td&gt;
&lt;td&gt;Tsubaki.3 nodes in PixAI Studio&lt;/td&gt;
&lt;td&gt;FLUX.1 Kontext Dev in the Edit tab&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On both platforms, I used only features that are also open to free accounts. Tensor.Art generated two images per run in this setup, since four-image batches need its Pro plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fixture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;hair_and_eyes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;copper-red short spiky high ponytail, gray-green eyes&lt;/span&gt;
&lt;span class="na"&gt;outfit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sleeveless navy coverall, yellow exoskeleton, hazard stripes on shoulder yoke&lt;/span&gt;
&lt;span class="na"&gt;asymmetric_detail&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;armor plate missing on the rig's left forearm, blue pistons exposed&lt;/span&gt;
&lt;span class="na"&gt;small_detail&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;single gold stud, right ear&lt;/span&gt;
&lt;span class="na"&gt;scene&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;exoskeleton lifts a cargo container with both mechanical arms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Stage 1: generation
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assertion&lt;/th&gt;
&lt;th&gt;PixAI&lt;/th&gt;
&lt;th&gt;Tensor.Art&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;hair and eyes&lt;/td&gt;
&lt;td&gt;pass&lt;/td&gt;
&lt;td&gt;partial (mismatched eyes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;outfit and palette&lt;/td&gt;
&lt;td&gt;pass&lt;/td&gt;
&lt;td&gt;partial (no stripes on yoke)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;left-forearm panel&lt;/td&gt;
&lt;td&gt;pass&lt;/td&gt;
&lt;td&gt;fail (right forearm)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;right-ear stud&lt;/td&gt;
&lt;td&gt;pass&lt;/td&gt;
&lt;td&gt;fail (dangling, left ear)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rig lifts the container&lt;/td&gt;
&lt;td&gt;fail (her own hands)&lt;/td&gt;
&lt;td&gt;fail (no lift)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Neither platform passed the scene assertion, and the results diverged on the trait assertions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 2: structured output
&lt;/h2&gt;

&lt;p&gt;The layout spec was an expression sheet: two rows of three, six named emotions in fixed cells, no text. PixAI's &lt;a href="https://blog.pixai.art/en/pixai-character-consistency-3-beginner-methods/" rel="noopener noreferrer"&gt;character consistency guide&lt;/a&gt; lists a reference image and a repeated description as separate methods, and I passed both.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PixAI, reference + text&lt;/td&gt;
&lt;td&gt;2x3 grid, 5 of 6 emotions in place, visible traits in all cells&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tensor.Art, IP-Adapter 1.0&lt;/td&gt;
&lt;td&gt;single blurred figure (this run also had two setup errors of mine)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tensor.Art, IP-Adapter 0.6&lt;/td&gt;
&lt;td&gt;about 11 faces in overlapping cells&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tensor.Art, text only&lt;/td&gt;
&lt;td&gt;clean 12-cell grid, all emotions present, costume changed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When I removed the reference add-on and kept the same text, the image came out clean, which points to the reference step in this setup. With one run per setting, I treat that as a lead, not a proof.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqiqz8gb0lqpsphwscya0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqiqz8gb0lqpsphwscya0.png" alt=" " width="799" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 3: edits as patches
&lt;/h2&gt;

&lt;p&gt;I started both edit chains from each platform's own Stage 1 image. In Edit 1, I asked for a new pose and a laugh and listed every trait to keep. In Edit 2, I used the Edit 1 result as input and switched the floodlights off, leaving an orange beacon as the only light.&lt;/p&gt;

&lt;p&gt;Think of each edit as a patch. With a good patch, only the requested lines change, and the rest of the file stays as it was.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;PixAI (Tsubaki.3)&lt;/th&gt;
&lt;th&gt;Tensor.Art (FLUX.1 Kontext Dev)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Edit 1 requested change&lt;/td&gt;
&lt;td&gt;applied&lt;/td&gt;
&lt;td&gt;laugh applied, container step had nothing to act on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit 1 unrequested diff&lt;/td&gt;
&lt;td&gt;pose to kneeling, rig leg became an arm, pistons switched sides&lt;/td&gt;
&lt;td&gt;new crouch, both eyes green&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit 2 requested change&lt;/td&gt;
&lt;td&gt;lights off, blue shadow&lt;/td&gt;
&lt;td&gt;frame darkened to about a third of its brightness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit 2 unrequested diff&lt;/td&gt;
&lt;td&gt;beacon moved, window reshaped, containers became cabinets&lt;/td&gt;
&lt;td&gt;almost none&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I got opposite results from the two chains. Tsubaki.3 applied each change and touched extra lines along the way. The Tensor.Art editing model touched a few extra lines and applied less of the requested change. In a third PixAI edit, I asked for a high camera angle, and the container disappeared entirely. That is the point where I would regenerate from the spec instead of patching again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fao3rtt3za27vbuhy9hp3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fao3rtt3za27vbuhy9hp3.png" alt=" " width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flwexx0fs2rg4ywrxmr7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flwexx0fs2rg4ywrxmr7y.png" alt=" " width="800" height="843"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run count
&lt;/h2&gt;

&lt;p&gt;I needed four runs on PixAI for the four steps and six on Tensor.Art, with both extra runs spent on the Stage 2 sheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways for your own pipeline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Write the spec as data and assert on every property after every stage.&lt;/li&gt;
&lt;li&gt;Include one asymmetric detail, since a left-right mix-up is easy to spot.&lt;/li&gt;
&lt;li&gt;Test reference settings on a throwaway run before a structured layout depends on them.&lt;/li&gt;
&lt;li&gt;Diff each edit against its input, and regenerate from the spec once unrequested diffs pile up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to run the same three stages on your own character, you can start on &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;PixAI&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>Flat Tag Lists Leak Attributes Between Characters: Testing Two Anime Generators</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Sun, 27 Sep 2026 12:02:01 +0000</pubDate>
      <link>https://dev.to/merl985/flat-tag-lists-leak-attributes-between-characters-testing-two-anime-generators-2ha0</link>
      <guid>https://dev.to/merl985/flat-tag-lists-leak-attributes-between-characters-testing-two-anime-generators-2ha0</guid>
      <description>&lt;p&gt;I wanted to know whether an anime image generator could keep a character's small details intact across a whole workflow, so I treated the character like a test fixture and ran the same suite on two platforms: PixAI with &lt;a href="https://eap.pixai.art/go/balazs2" rel="noopener noreferrer"&gt;Tsubaki.3&lt;/a&gt;, and SeaArt with a popular community anime checkpoint plus SeaArt's own reference and editing tools. On both, I only used features that free accounts can also use.&lt;/p&gt;

&lt;p&gt;I expected to separate the two platforms by image quality. Instead, I kept tracing failures back to one question: how does each prompt format bind attributes to the right subject?&lt;/p&gt;

&lt;h2&gt;
  
  
  The fixture
&lt;/h2&gt;

&lt;p&gt;The character is Aldric, a clumsy wizard who cooks for an adventuring party. His spec:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;character&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Aldric&lt;/span&gt;
&lt;span class="na"&gt;hair&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ginger, short ponytail&lt;/span&gt;
&lt;span class="na"&gt;beard&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;short, ginger&lt;/span&gt;
&lt;span class="na"&gt;eyes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pale blue&lt;/span&gt;
&lt;span class="na"&gt;robe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mustard yellow, hood down, sleeves cut at the elbow&lt;/span&gt;
&lt;span class="na"&gt;belt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wide, brown, exactly 3 wooden spoons&lt;/span&gt;
&lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;crooked wooden wand&lt;/span&gt;
&lt;span class="na"&gt;legs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cream trousers, rust brown boots&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The spoon count is the assertion I trusted most. A face can look right by accident, while three spoons are either on the belt or missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The suite
&lt;/h2&gt;

&lt;p&gt;I fixed the budget before the first run: one batch of four images per new scene, one allowed prompt revision for the whole suite, and up to two tries per edit step.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Case&lt;/th&gt;
&lt;th&gt;Input change&lt;/th&gt;
&lt;th&gt;Assertion&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A. Create&lt;/td&gt;
&lt;td&gt;baseline&lt;/td&gt;
&lt;td&gt;all spec fields present&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B. Crowded scene&lt;/td&gt;
&lt;td&gt;second character, eight requirements&lt;/td&gt;
&lt;td&gt;every attribute on the correct person&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C. Reuse&lt;/td&gt;
&lt;td&gt;two new scenes from a reference image&lt;/td&gt;
&lt;td&gt;spec fields unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D. Edit twice&lt;/td&gt;
&lt;td&gt;outfit change, then setting and light&lt;/td&gt;
&lt;td&gt;change applied, everything else unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  One spec, two serializations
&lt;/h2&gt;

&lt;p&gt;Tsubaki.3 reads plain sentences. The checkpoint on SeaArt expects comma-separated tags. So I wrote the same spec in two formats.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PixAI:  "...a wide brown leather belt with exactly three wooden
         spoons tucked into it, cream trousers, and rust brown boots..."

SeaArt: "...wide brown leather belt, three wooden spoons tucked in
         belt, cream pants, brown boots..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assertion&lt;/th&gt;
&lt;th&gt;PixAI, Tsubaki.3&lt;/th&gt;
&lt;th&gt;SeaArt, community checkpoint&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3 spoons, case A&lt;/td&gt;
&lt;td&gt;4 of 4&lt;/td&gt;
&lt;td&gt;0 of 4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crooked wand, case A&lt;/td&gt;
&lt;td&gt;4 of 4&lt;/td&gt;
&lt;td&gt;0 of 4, walking staff instead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attributes on the correct person, case B&lt;/td&gt;
&lt;td&gt;4 of 4&lt;/td&gt;
&lt;td&gt;1 of 4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3 spoons, case C&lt;/td&gt;
&lt;td&gt;5 of 8&lt;/td&gt;
&lt;td&gt;1 of 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit 1 applied, rest unchanged&lt;/td&gt;
&lt;td&gt;yes, first try&lt;/td&gt;
&lt;td&gt;yes, first try&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit 2 applied&lt;/td&gt;
&lt;td&gt;yes, relit for the new scene&lt;/td&gt;
&lt;td&gt;background changed, lighting unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxu4dq6iv19igpox8zuej.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxu4dq6iv19igpox8zuej.jpg" alt=" " width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Case C on SeaArt has two images instead of eight because I ran its Character Reference with one image per run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why tag lists leak
&lt;/h2&gt;

&lt;p&gt;SeaArt had the most trouble with case B. In three of the four SeaArt images, the model mixed up the two characters: one image split Aldric into a gray-bearded man and a ginger-haired woman in his robe, and another put the robe on a black-haired stranger.&lt;/p&gt;

&lt;p&gt;As an analogy, think of a tag prompt as one flat array with no object boundaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tag prompt: every attribute in one list, no owner&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1boy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1other&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ginger beard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mustard yellow robe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;black bob hair&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grey hooded cloak&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;holding empty wooden bowl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;// sentence prompt: attributes scoped to their subject&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;wizard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;beard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ginger&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;robe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mustard yellow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;companion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;hair&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;black bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cloak&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gray&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;holds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;empty bowl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the flat version, the model has to infer which attribute belongs to which subject. In the scoped version, I answer that question in the prompt itself. This is a mental model for writing prompts, and I am not describing either model's internals.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fddc2v7eeh6m3ftwwczed.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fddc2v7eeh6m3ftwwczed.jpg" alt=" " width="799" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The one revision
&lt;/h2&gt;

&lt;p&gt;Tsubaki.3 still missed two requirements in case B, in all four images: the cauldron was supposed to float above the fire, and noodles were supposed to hang from Aldric's beard. The &lt;a href="https://blog.pixai.art/en/tsubaki-3-prompt-guide/" rel="noopener noreferrer"&gt;Tsubaki.3 Prompt Guide&lt;/a&gt; recommends describing spatial relationships in full sentences, so I gave each missed detail its own sentence and left everything else untouched:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The cauldron hovers in mid-air by magic, with a clear gap of empty air
between its round bottom and the tips of the flames, and nothing holds it up.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both assertions went from 0 of 4 to 4 of 4. One unrelated assertion regressed: the three carrot slices on the cave wall appeared in 2 of 4 images before the change and in 0 of 4 after it. I logged that as a side effect of the rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reuse copies state you did not ask for
&lt;/h2&gt;

&lt;p&gt;For case C, I gave PixAI the first image as a reference in the prompt box and described only the new scene. Face, beard and bare head matched in all eight images. A leather pouch that I never specified in case A also appeared in seven of the eight, because it was in the reference image.&lt;/p&gt;

&lt;p&gt;SeaArt's Character Reference showed the same behavior in a different form. In the reading scene, it copied the reference background, chests and fire included. In the river scene, the belt count went from three spoons to five or six.&lt;/p&gt;

&lt;p&gt;I now treat a reference image as a snapshot of state. Everything in it is input, including accidents.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxhso3x5088p7zum333j1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxhso3x5088p7zum333j1.jpg" alt=" " width="800" height="1127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The edit chain as a pipeline
&lt;/h2&gt;

&lt;p&gt;Case D had two steps: add a stew stain to the robe, then move Aldric to a sunset hillside. I used the stain as a canary value. If step 2 had used the original image instead of the result of step 1, the stain would have disappeared.&lt;/p&gt;

&lt;p&gt;On PixAI, I linked the steps as nodes in PixAI Studio, with Tsubaki.3 in every node. The stain stayed through step 2, and Tsubaki.3 relit Aldric for the sunset, with a small drift: a new smear on his cheek and a slightly different wand.&lt;/p&gt;

&lt;p&gt;On SeaArt, the stain also stayed, and Aldric came through step 2 almost pixel-identical. The lighting on him did not change, so he looks out of place in the new scene. SeaArt also returned the first edit at a smaller size than the input, 864 pixels wide instead of 1152, and its reference and editing windows have no negative prompt field.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would reuse
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Write each subject as its own sentence block when the model reads sentences.&lt;/li&gt;
&lt;li&gt;Put one countable detail in every character spec. With it, "looks about right" becomes a pass or fail.&lt;/li&gt;
&lt;li&gt;Use a canary value in multi-step edits to confirm which image each step used as input.&lt;/li&gt;
&lt;li&gt;Check the reference image for accidents before reusing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to run the same suite on your own character, you can &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;start on PixAI&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>Unit-Testing an Anime Prompt: Nine Assertions on a Civitai Alternative</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Tue, 22 Sep 2026 20:41:24 +0000</pubDate>
      <link>https://dev.to/merl985/unit-testing-an-anime-prompt-nine-assertions-on-a-civitai-alternative-5ae6</link>
      <guid>https://dev.to/merl985/unit-testing-an-anime-prompt-nine-assertions-on-a-civitai-alternative-5ae6</guid>
      <description>&lt;p&gt;The anime model I tried on Civitai this summer used tag lists, and for hard poses, model-library workflows offer pose-guide add-ons such as ControlNet, which PixAI also offers on its other models. &lt;a href="https://eap.pixai.art/go/balazs2" rel="noopener noreferrer"&gt;Tsubaki.3&lt;/a&gt;, PixAI's newest anime model, takes full sentences and also handles references and edits in the same model. I wanted numbers instead of impressions, so I treated each prompt like a test case: a fixed spec, a batch of four, and a pass count for every requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; Every run used Tsubaki.3, with batches of four for new scenes and single images for edits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preprocessing:&lt;/strong&gt; I switched off Prompt Helper, PixAI's automatic prompt rewriter, so each result reflects my own wording.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extras:&lt;/strong&gt; I used no style preset, no Recipe and no LoRA.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The fixture
&lt;/h2&gt;

&lt;p&gt;The character is Sorane, a street dance crew captain I created for this test. Her spec had seven checkable traits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;hair&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tangerine bob, undercut on the right side&lt;/span&gt;
&lt;span class="na"&gt;eyes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;teal&lt;/span&gt;
&lt;span class="na"&gt;face_mark&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;small black star tattoo under the left eye&lt;/span&gt;
&lt;span class="na"&gt;jacket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oversized lime track jacket, exactly 3 white chest stripes, off the left shoulder&lt;/span&gt;
&lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;black tank top&lt;/span&gt;
&lt;span class="na"&gt;legs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;charcoal cargo joggers, red bandana on the right thigh&lt;/span&gt;
&lt;span class="na"&gt;shoes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;white high-tops, red laces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first batch, eyes, star, tank top, bare shoulder, bandana and sneakers passed 4/4. The stripe count passed 1/4. The undercut side failed 4/4: it landed on her left, next to the star. I kept the image with three stripes as the fixture for every later test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 1: a hard pose from text alone
&lt;/h2&gt;

&lt;p&gt;In the next prompt, I described a two-person breaking battle: Sorane upside down on one hand, a silver-haired opponent mid-jump on the right, a floor-level wide-angle camera, a dark crowd, two crossing spotlights and puddles.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assertion&lt;/th&gt;
&lt;th&gt;Passed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;upside-down one-hand pose, knees bent&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opponent mid-jump, knees tucked&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;left and right placement&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;colors stay with their own character&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;no feature copied to the other character&lt;/td&gt;
&lt;td&gt;3/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;crowd as dark silhouettes&lt;/td&gt;
&lt;td&gt;3/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;spotlight beams crossing&lt;/td&gt;
&lt;td&gt;1/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shadows falling toward the camera&lt;/td&gt;
&lt;td&gt;0/4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The pose and placement passed from text alone. The lighting assertions failed most often.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 2: nine assertions in one prompt
&lt;/h2&gt;

&lt;p&gt;I stacked nine requirements into the staircase prompt. I asked for the seven traits, a mid-air jump down the stairs, an open-mouthed laugh, a high camera and a corner-to-corner staircase. I also asked for exactly five cones in a row, a blue "EXIT 7" sign, rain on wet steps, and one yellow streetlamp near the top-right corner throwing her shadow toward the lower left.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assertion&lt;/th&gt;
&lt;th&gt;Passed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;jump, laugh, high angle, rain&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lamp near the top-right corner&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shadow toward the lower left&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wet, reflective steps&lt;/td&gt;
&lt;td&gt;3/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sign with clean "EXIT 7" lettering&lt;/td&gt;
&lt;td&gt;1/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exactly five cones&lt;/td&gt;
&lt;td&gt;1/4 (counts: 4, 4, 5, 4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;staircase running corner to corner&lt;/td&gt;
&lt;td&gt;0/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lamp as the only light source&lt;/td&gt;
&lt;td&gt;0/4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Compare the shadow rows across both tests. In Test 1, I named two spotlights on the pillars but gave them no place in the frame, and the shadow assertion failed 0/4. In Test 2, I named one lamp, its position in the frame and the shadow direction, and it passed 4/4. PixAI's &lt;a href="https://blog.pixai.art/en/tsubaki-3-prompt-guide/" rel="noopener noreferrer"&gt;Tsubaki.3 prompt guide&lt;/a&gt; recommends naming the light source, and these two runs are consistent with that.&lt;/p&gt;

&lt;p&gt;I also tried isolating the failing assertion. On the image with the clean sign, I ran one edit, asking only for five cones in a straight, visible row. The row came out straight and visible, and it still had four cones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx1llza1fdbgm5oi1stt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx1llza1fdbgm5oi1stt.jpg" alt=" " width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 3: the reference image as a fixture
&lt;/h2&gt;

&lt;p&gt;Tsubaki.3 takes a reference image in the prompt box, called &lt;code&gt;@image1&lt;/code&gt; in the text. I passed the fixture and described only the change, following PixAI's own advice: a rooftop at sunrise, then a waist-up studio shot in blue evening light, four images each.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check across 8 images&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;star tattoo under the left eye&lt;/td&gt;
&lt;td&gt;8/8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;undercut at reference size&lt;/td&gt;
&lt;td&gt;2/8 (grew into a half-shaved head in 6)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jacket hue close to reference (studio set)&lt;/td&gt;
&lt;td&gt;0/4 (darker, cooler green)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;unrequested sleeve stripe from the reference&lt;/td&gt;
&lt;td&gt;about half&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The stripe in the last row was never in my prompt, yet it came back in about half of the new images. In my runs, accidental details in a reference were copied like intended ones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq0iib42fba3xmok20elh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq0iib42fba3xmok20elh.jpg" alt=" " width="799" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 4: edits as patches
&lt;/h2&gt;

&lt;p&gt;I applied two edits in sequence. In the first, I swapped only the jacket for a crimson satin bomber and listed everything to keep. It worked on the first run, with four side effects: the jacket hung open, the tank top became a T-shirt, one hand moved into a pocket, and a drawstring appeared on the joggers. With the second edit, applied to the first result, I moved her into a night scene. The setting, light and shadow direction passed, while the red laces turned white and the drawing style shifted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9li8o0990pmr7v3gyx96.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9li8o0990pmr7v3gyx96.jpg" alt=" " width="799" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would tell another developer
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Write scene requirements as sentences, and test each one separately across a batch.&lt;/li&gt;
&lt;li&gt;Make lighting assertions specific: source, position and shadow direction.&lt;/li&gt;
&lt;li&gt;Treat exact counts as unreliable and check them by hand.&lt;/li&gt;
&lt;li&gt;Diff every reference-based result against the reference, including details you never asked for.&lt;/li&gt;
&lt;li&gt;Keep edits narrow and check for side effects after each one, since both of my edits had some.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to run the same kind of test on your own character, start with a written spec and a batch of four on &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;PixAI&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>Treating an AI Anime Character Generator Like a Function With Default Arguments</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Mon, 21 Sep 2026 12:48:40 +0000</pubDate>
      <link>https://dev.to/merl985/treating-an-ai-anime-character-generator-like-a-function-with-default-arguments-jag</link>
      <guid>https://dev.to/merl985/treating-an-ai-anime-character-generator-like-a-function-with-default-arguments-jag</guid>
      <description>&lt;p&gt;&lt;a href="https://eap.pixai.art/go/balazs2" rel="noopener noreferrer"&gt;Tsubaki.3&lt;/a&gt;, the newest anime model on PixAI, is now officially released, and I used the release week for a small controlled test. I took one original character from a three-sentence spec to a design I would keep developing, changing one layer at a time and logging what each step changed. If you think in code, the process maps neatly onto a function call with default arguments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Subject:&lt;/strong&gt; Kazane is a broom-racing witch I created for this test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; Every run used Tsubaki.3, with batches of four for the text-only runs and single images for the reference runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preprocessing:&lt;/strong&gt; Prompt Helper was on in every run. It rewrites the prompt before generation, and each image's detail page shows the rewritten version next to the original.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Out of scope:&lt;/strong&gt; I skipped LoRAs. PixAI's &lt;a href="https://blog.pixai.art/en/model-vs-lora-pixai-foundations/" rel="noopener noreferrer"&gt;model vs LoRA explainer&lt;/a&gt; covers when one is worth adding; my questions were about individual clothing pieces.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Run 1: most arguments unset
&lt;/h2&gt;

&lt;p&gt;In the first prompt, I passed three values and left everything else open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;generate_character&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;loud, competitive witch who races brooms between floating islands&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flies bareheaded, anything on her head would slow her down&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;style_note&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dressed for speed rather than for a storybook&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# hair, eyes, outfit and footwear were never passed
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Batch 1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Recognizable anime witch on a broom&lt;/td&gt;
&lt;td&gt;4/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bareheaded, as specified&lt;/td&gt;
&lt;td&gt;1/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anything resembling racing gear&lt;/td&gt;
&lt;td&gt;0/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Looks like an adult in her twenties&lt;/td&gt;
&lt;td&gt;0/4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distinct hair colors&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The unset arguments resolved to the most familiar version of "witch": pointed hats, dark robes, school uniforms and red ribbons. In three images, that default replaced a value I had passed explicitly. The spec described a bareheaded racer, and three of the four images showed the stock witch instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run 2: pass the values explicitly
&lt;/h2&gt;

&lt;p&gt;I treated the batch as a diff to review. I kept the bareheaded image, the shouting expression and the trailing fabric. I rejected the hat, ribbon, robe and skirt, and I replaced the reddish hair and the teenage look. Then I appended each decision to the unchanged original three sentences:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;generate_character&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;...,&lt;/span&gt;  &lt;span class="c1"&gt;# the original three sentences, verbatim
&lt;/span&gt;    &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;top of her head and full hairstyle visible&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hair&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deep plum, single high ponytail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;eyes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;golden yellow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fitted midnight-navy racing top with a zip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;capelet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;short, teal, right shoulder only&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;black trousers tucked into white knee boots&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;broom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exactly three teal bands&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;head&lt;/code&gt; argument describes what must be visible instead of passing a negative flag like "no hat". Batch 2 changed many values at once, so I cannot credit the bare head to this line alone. The head stayed bare in 4/4 images, and hair, eyes, top, trousers, boots and broom bands matched in every image.&lt;/p&gt;

&lt;p&gt;Two values still varied because I had left them loose or unset. The trailing fabric came out navy three times and teal once, and the broom handle's end changed shape. The pose also repeated across all eight images: she hovers over a rock ledge instead of riding the banked turn I asked for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0qzoetfqfucvccwdn4uk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0qzoetfqfucvccwdn4uk.jpg" alt=" " width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run 3: images as arguments, and the scope bug
&lt;/h2&gt;

&lt;p&gt;Tsubaki.3 accepts two reference images in the prompt box, addressed as &lt;code&gt;@image1&lt;/code&gt; and &lt;code&gt;@image2&lt;/code&gt;. I passed the refined character as &lt;code&gt;@image1&lt;/code&gt; and a photo of a monarch butterfly as &lt;code&gt;@image2&lt;/code&gt;, then compared two scopes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# wide scope
&lt;/span&gt;&lt;span class="nf"&gt;redesign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outfit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;image2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# narrow scope
&lt;/span&gt;&lt;span class="nf"&gt;redesign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;capelet and its trailing fabric&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;image2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;keep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;navy top&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;black trousers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;white knee boots&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;Pattern source&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;butterfly&lt;/td&gt;
&lt;td&gt;whole outfit&lt;/td&gt;
&lt;td&gt;pattern on the entire suit; top, capelet, trousers and boots lost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;soap bubble&lt;/td&gt;
&lt;td&gt;whole outfit&lt;/td&gt;
&lt;td&gt;swirl pattern on the entire suit; white boots kept&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;butterfly&lt;/td&gt;
&lt;td&gt;capelet only&lt;/td&gt;
&lt;td&gt;pattern on the capelet; top, trousers and boots kept, one sleeve turned orange&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Reading the Rewritten Prompt for run A explained the result. My wide wording became "a fully covering racing suit patterned after the butterfly", so the rewrite kept my wide scope and stated it even more broadly. In the narrow-scope version, the rewrite kept every named item almost word for word. The practical rule: when you pass an image, pass the scope with it.&lt;/p&gt;

&lt;p&gt;One more edge case: an earlier attempt that described the capelet's "streaming tail" produced a furry tail beside the fabric. Tokens like tail, wing and horn can resolve to anatomy, so I now describe those pieces as fabric.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb8hilcbt4xdu3342biq7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb8hilcbt4xdu3342biq7.jpg" alt=" " width="800" height="1123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run 4: a style layer as a regression test
&lt;/h2&gt;

&lt;p&gt;Recipes are reusable prompt add-ons in the Tsubaki.3 generator panel, and PixAI Official publishes style Recipes among them. I reran the narrow-scope setup with the Holographic Recipe switched on. Face, hair, eyes and broom bands passed. The outfit scope, the background and the camera distance all changed.&lt;/p&gt;

&lt;p&gt;I read that like a failing regression test. The traits that passed are stable enough to build on, and the ones that failed need locking before I explore looks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flhayj4ujn9jzj4b5tniy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flhayj4ujn9jzj4b5tniy.jpg" alt=" " width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would tell another developer
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Unset arguments get defaults from the role word, and those defaults can override values you did pass.&lt;/li&gt;
&lt;li&gt;Describe what should be present instead of passing negations.&lt;/li&gt;
&lt;li&gt;Keep the original spec verbatim and append decisions, so each batch is a clean diff.&lt;/li&gt;
&lt;li&gt;Pass scope explicitly with every reference image, and read the Rewritten Prompt when a result surprises you.&lt;/li&gt;
&lt;li&gt;Check ambiguous tokens like tail, wing or horn before a run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to run the same experiment on your own character, start with a three-sentence spec and a batch of four on &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;PixAI&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>I Ran a Five-Step Image Pipeline Entirely on a Phone</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Wed, 16 Sep 2026 08:41:26 +0000</pubDate>
      <link>https://dev.to/merl985/i-ran-a-five-step-image-pipeline-entirely-on-a-phone-3ahi</link>
      <guid>https://dev.to/merl985/i-ran-a-five-step-image-pipeline-entirely-on-a-phone-3ahi</guid>
      <description>&lt;p&gt;Most write-ups about mobile AI image apps stop at the first generation. That is the easy case. The interesting question is whether a full pipeline runs on a phone: generate, swap the model, condition on a reference, edit a region, then retrieve the artifact later.&lt;/p&gt;

&lt;p&gt;I ran that pipeline end to end in the PixAI mobile app, on an iPhone, with the laptop closed. Below is the setup, the controls, and what each step produced.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fixture
&lt;/h2&gt;

&lt;p&gt;The prompt runs to about a hundred and twenty words and describes a character and a scene: subject, clothing, pose, environment, light direction, camera position. Five visual identifiers in the description that are easy to check in an output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Identifier&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hair&lt;/td&gt;
&lt;td&gt;copper-red, cropped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jacket&lt;/td&gt;
&lt;td&gt;dark green band jacket with a wide cream diagonal sash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Undershirt&lt;/td&gt;
&lt;td&gt;black, high collar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trousers&lt;/td&gt;
&lt;td&gt;cream with a single green side stripe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prop&lt;/td&gt;
&lt;td&gt;brass tuba&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Everything else varied one axis at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: baseline generation
&lt;/h2&gt;

&lt;p&gt;The generate screen puts LoRA, model, style, mode, output size, and quantity into one horizontally scrolling row under the prompt card. One run returned four images at the quantity setting shown.&lt;/p&gt;

&lt;p&gt;The bottleneck is text entry, not compute. With the keyboard open, the prompt field is a few lines tall, so proofreading a long description means scrolling inside a small window. If you build prompts programmatically or keep them in a notes file, paste them in rather than typing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj8dgup1zj227n1m5jfoe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj8dgup1zj227n1m5jfoe.jpg" alt=" " width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: model swap, seed held constant
&lt;/h2&gt;

&lt;p&gt;The second run used the same prompt string and the same seed on a different base model. A seed fixes the random starting point, so holding it constant removes one variable.&lt;/p&gt;

&lt;p&gt;The model picker has three tabs: Preset for official models, Collection for saved ones, and Market for community uploads. Every card is labeled with its architecture family, so DiT.2, DiT.1, or XL, which is the practical signal for what kind of prompt the model prefers. The swap took three taps, and the session continued without a restart.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assertion&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Written identifiers reappear on model B&lt;/td&gt;
&lt;td&gt;Pass, all five&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Face and proportions match model A&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rendering style matches model A&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same seed reproduces the composition&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last row is the one that changes how you store a character definition. A seed indexes noise inside one model. Across two models, the same integer produced no resemblance at all. Prompt text is the portable part of a character definition, and the seed is not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnf69i6n7ibifp64wnpin.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnf69i6n7ibifp64wnpin.jpg" alt=" " width="799" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: reference conditioning
&lt;/h2&gt;

&lt;p&gt;The reference workflow is exposed as a preset in the model list rather than as a separate mode, which means selecting it replaces your base model selection. Worth knowing before you plan a session around it.&lt;/p&gt;

&lt;p&gt;The panel enforces an order: the image loads first, and the prompt field stays inactive until it does. I had a paragraph ready and could not enter a character of it until the reference was in place.&lt;/p&gt;

&lt;p&gt;The input came from the camera roll, where the previous step had already saved it. That is the structural argument for doing this work on a phone. The source artifact and the output destination are the same device, so the file transfer step disappears.&lt;/p&gt;

&lt;p&gt;Conditioning on the earlier output plus a short new-scene description returned the same character in a different location. Hair, sash, collar, and instrument came back intact, with nothing about the character repeated in the prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: masked edit
&lt;/h2&gt;

&lt;p&gt;Edit opens a canvas with Inpaint and Outpaint as separate tabs, and mask size, brush, eraser, mask shape, and feather along the bottom. A small box in the corner previews where the masked region falls on the image.&lt;/p&gt;

&lt;p&gt;I masked one element and requested a change there. Measured against the source file, the marked band came back about a third wider at mid-chest, while the buttons, the hand, the mouthpiece, and the collar were unchanged. Whatever else you think of the result, containment held: the diff concentrates inside the mask by a wide margin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: retrieval
&lt;/h2&gt;

&lt;p&gt;Library opens on a menu of collections, published work and likes, with Recent Tasks below it. Each run is a card titled with the opening words of its own prompt, stamped with a date and time, and the list has a search box above it.&lt;/p&gt;

&lt;p&gt;Open a single result, and the next actions are on one screen: Download, Publish, Animate, Edit, Import to Generate, and Re-roll. Import to Generate pulls that run's prompt and model back into the generate screen, which is the resume-session path.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzt7rx6dwcvepl8pwcotf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzt7rx6dwcvepl8pwcotf.jpg" alt=" " width="800" height="805"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What a phone is bad at
&lt;/h2&gt;

&lt;p&gt;Long prompt editing, because the visible field is small. Comparing several outputs at once, because a run returns thumbnails, and judging them at full size means opening one at a time. Detail review, because a small display hides errors: one of my outputs has a clearly elongated forearm that I only noticed on a laptop. And finding a rarely used control, since there is less room off the main path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verdict
&lt;/h2&gt;

&lt;p&gt;The pipeline ran five steps on one device with no restarts, end-to-end on a phone, and the constraints are input and review rather than capability. If you want to run the same test, four checks matter: the model picker has to expose metadata, the reference input has to accept a local file, the editor has to respect a mask, and the history has to be searchable.&lt;/p&gt;

&lt;p&gt;For where each control is in the interface, the PixAI app guide covers it screen by screen: &lt;a href="https://blog.pixai.art/en/pixai-app-guide/" rel="noopener noreferrer"&gt;https://blog.pixai.art/en/pixai-app-guide/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;Try the same pipeline on PixAI&lt;/a&gt; and see how far your phone takes you.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>Free tier, real workflow: what I learned testing an anime image generator on one character</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Sun, 13 Sep 2026 09:12:58 +0000</pubDate>
      <link>https://dev.to/merl985/free-tier-real-workflow-what-i-learned-testing-an-anime-image-generator-on-one-character-13l1</link>
      <guid>https://dev.to/merl985/free-tier-real-workflow-what-i-learned-testing-an-anime-image-generator-on-one-character-13l1</guid>
      <description>&lt;p&gt;Most write-ups about free image generation stop at the credit count. That number tells you almost nothing, because what decides whether a free tier is usable is how much of the pipeline it exposes and where it hard-stops.&lt;/p&gt;

&lt;p&gt;I ran a session on PixAI to find out, using one original character as a fixed test subject and staying on features a never-paid account can reach. Three findings are worth passing on, and all three are the kind of thing you only hit by actually running the thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;The subject was a surfer with a deliberately over-specified design: turquoise streak on the left of the hair, green eyes, short asymmetric wetsuit with the right arm bare, orange leash on the left ankle, beaded bracelet on the right wrist, shell earring on the right ear, board with three stripes. That gives seven checkable attributes, several of them side-specific and one of them countable.&lt;/p&gt;

&lt;p&gt;That is a test harness, not a character sheet. Side-specific and countable attributes fail visibly, which means you can grade an output instead of squinting at it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgv3c0ht5c7aqx5rf1qak.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgv3c0ht5c7aqx5rf1qak.jpg" alt="The baseline generation. Seven specified attributes, a scene, a light direction, and a camera angle, produced from a single prompt with no editing after." width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding one: prompt syntax belongs to the model family, not the platform
&lt;/h2&gt;

&lt;p&gt;The platform hosts two architecture families. The DiT models parse natural-language sentences. The SDXL-derived models respond to tag-style input. Running the same character through one model from each meant rewriting the prompt, not swapping a dropdown.&lt;/p&gt;

&lt;p&gt;The rewrite is where things broke. Hair color, the streak, and the eye color carried over. Everything else drifted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;orange ankle leash on left ankle&lt;/code&gt; rendered as orange boots on both feet&lt;/li&gt;
&lt;li&gt;the three board stripes vanished entirely&lt;/li&gt;
&lt;li&gt;the shell earring became a turquoise stud&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;right shoulder and arm bare&lt;/code&gt; collapsed into a bare shoulder with both sleeves intact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6h5ivjh3t1zl78nkx8ge.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6h5ivjh3t1zl78nkx8ge.jpg" alt="Same subject, two model families. The crops underneath are cut from the same two files at full resolution, since the failing attributes measure about ten pixels across at feed scale." width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some of that is the model, and some is my tag translation, and I cannot cleanly separate the two from one test. The transferable point stands either way: switching model families is a prompt rewrite, and every attribute you care about needs re-anchoring in the new syntax. Treat your prompt as source coupled to a target, not as portable input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding two: LoRAs are architecture-bound dependencies
&lt;/h2&gt;

&lt;p&gt;LoRAs are small adapter files that steer a base model toward a specific style, outfit, character, or concept. Free accounts can load them into normal generation, which is the part that makes a free tier interesting rather than decorative.&lt;/p&gt;

&lt;p&gt;The dependency behavior is the useful bit. Each LoRA is trained against a specific base model and loads only onto matching ones. The browser has no architecture filter, so the ecosystem solved it socially: creators write the architecture into the LoRA name. Searching &lt;code&gt;dit.2&lt;/code&gt; returns results literally named &lt;code&gt;Yuu_style DiT.2&lt;/code&gt;, &lt;code&gt;BotanInk(DiT.2)&lt;/code&gt;, &lt;code&gt;ColorSnapVibe(DiT.2)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq31q2drfg4qnyqzzf9cu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq31q2drfg4qnyqzzf9cu.jpg" alt="The adapter loaded at strength 0.7, with  raw `dit.2` endraw  in the search box. Every result carries the architecture in its name, which is the ecosystem routing around a missing filter." width="656" height="1240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every LoRA card carries a base model field, and loading the LoRA sets that base model for you. The consequence is worth stating plainly: your adapter choice determines your base model, so on a free account part of your control decision resolves before you generate anything.&lt;/p&gt;

&lt;p&gt;One more practical note. The first adapter I picked had a trigger word list running to nine separate instructions, all of them about eyelashes and under-eye detail. The model obliged by building an extra eye onto the character's cheek. Read the trigger list before loading, the same way you would read a package's peer dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding three: a seed does not survive a mode change
&lt;/h2&gt;

&lt;p&gt;The platform offers two generation modes, both open to free accounts, differing in cost and compute. I assumed the cheaper mode would give me the same image at lower fidelity, so I ran one prompt through both with the seed pinned.&lt;/p&gt;

&lt;p&gt;It gave me sibling images, not the same image at two quality settings. Measured on a coarse layout comparison, the pair sat inside the same similarity range as two other outputs from the same batch. The prompt explains the resemblance; the seed contributed nothing measurable across the boundary.&lt;/p&gt;

&lt;p&gt;That has a workflow implication. If you explore cheaply and find a composition you like, you cannot promote it to the expensive mode by reusing the seed. The modes are separate generations, so explore in whichever mode you intend to finish in.&lt;/p&gt;

&lt;p&gt;Where the two modes did differ was background detail. The water carried noticeably less fine texture in the cheaper mode while the face barely changed. One pair is thin evidence for a rule, so run the check on your own subject before committing a day's budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the free tier actually gates
&lt;/h2&gt;

&lt;p&gt;Two categories get conflated constantly, and separating them is most of the analysis:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unavailable without paying.&lt;/strong&gt; The fastest generation queue, the video tools, the reference-based consistency tools, and a monthly adapter training allowance. The &lt;a href="https://blog.pixai.art/en/membership-payment-faq-web/" rel="noopener noreferrer"&gt;membership and payment information&lt;/a&gt; page carries the specifics, and it is worth reading rather than trusting my summary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Available, and metered.&lt;/strong&gt; Everything else. That covers both generation modes, the public model library, community adapters and the standard image sizes. Lean on any of them and the daily allowance drains faster, which is a budget constraint rather than a wall. The &lt;a href="https://blog.pixai.art/en/pixai-free-credits-guide/" rel="noopener noreferrer"&gt;free credits guide&lt;/a&gt; covers the refill mechanics.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I did not expect
&lt;/h2&gt;

&lt;p&gt;I assumed the first generation would be the best one and everything after would be cleanup. The opposite happened. My character's description never fully landed until the fourth stage, after the model and the adapter were settled and the scene had changed completely. The final image carried every specified attribute at once, including the countable one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn9k6dc2aq6jpnkp40jzh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn9k6dc2aq6jpnkp40jzh.jpg" alt="Stage one on the left, stage four on the right. Same model, same adapter, same character block, everything else replaced." width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For anyone benchmarking a free tier, that is the measurement worth taking. A tier that produces one good image and locks the door behind it is a demo. A tier that lets you converge across four generations is a tool, and the convergence is the thing to test.&lt;/p&gt;

&lt;p&gt;The whole session ran to roughly a dozen generation jobs across four configurations, entirely on the free side. If you want to reproduce the method, &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;the platform is here&lt;/a&gt;. Pick a subject with side-specific and countable attributes, and grade the outputs instead of admiring them.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
    <item>
      <title>An Anime Image Model Is a Flaky Dependency, So I Asserted on Every Property Twice</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Thu, 10 Sep 2026 16:11:10 +0000</pubDate>
      <link>https://dev.to/merl985/an-anime-image-model-is-a-flaky-dependency-so-i-asserted-on-every-property-twice-4g21</link>
      <guid>https://dev.to/merl985/an-anime-image-model-is-a-flaky-dependency-so-i-asserted-on-every-property-twice-4g21</guid>
      <description>&lt;p&gt;Image models are nondeterministic functions. Same input, different output, and the variance is controlled by a seed you can pin. Anyone who has written tests against a flaky service already knows what that implies: a single call proves nothing. You need a second call with one variable changed, or you are reading noise as behavior.&lt;/p&gt;

&lt;p&gt;The comparisons I read mostly skip this. One image per product, results side by side, call it a benchmark. So I ran a proper version on one anime image platform, with a control run for every claim.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fixture
&lt;/h2&gt;

&lt;p&gt;I built one test character with assertable properties, the way you would design a fixture rather than a mood board:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dark brown bob cut straight at the jawline&lt;/li&gt;
&lt;li&gt;pale grey green eyes&lt;/li&gt;
&lt;li&gt;a mustard base layer whose &lt;strong&gt;left&lt;/strong&gt; sleeve turns charcoal below the elbow&lt;/li&gt;
&lt;li&gt;exactly &lt;strong&gt;four&lt;/strong&gt; tool loops on the &lt;strong&gt;right&lt;/strong&gt; thigh&lt;/li&gt;
&lt;li&gt;a charcoal patch on the &lt;strong&gt;left&lt;/strong&gt; knee&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two of those are side-specific, one is countable, two are pure color. Side and count are the ones worth including, because a symmetrical character with no countable elements passes every test by accident.&lt;/p&gt;

&lt;p&gt;All runs used the same model, mode and settings, with only the stated variable changed between a run and its control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 1, prompt following with a batch instead of a single call
&lt;/h2&gt;

&lt;p&gt;Ten checkable instructions in one prompt, generated four times with nothing changed but the seed.&lt;/p&gt;

&lt;p&gt;Six instructions appeared in all four outputs: the camera framing, which hand held which object, the two-color sleeve on the correct arms, the loops on the correct thigh, the patch on the correct knee, and the eye color. Those are model behavior and you can build on them.&lt;/p&gt;

&lt;p&gt;One failed in all four: the requested low camera angle never arrived. The count landed once, as four straps on a tool roll the model invented, and came back as six, seven and six in the others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbskdfff7cwe582y6orul.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbskdfff7cwe582y6orul.jpg" alt=" " width="800" height="1129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I later ran the same prompt four more times with a single color word changed. Across those eight generations, the correct count of four appeared twice. A single sample would have supported either conclusion, which is the argument for control runs in one number.&lt;/p&gt;

&lt;p&gt;One more thing surfaced only because there were four outputs. The prompt asked for the object at chest height and for the character to look up. Exactly one output satisfied the first, and it is the same output that failed the second. The model coupled two instructions I had written as independent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 2, state across calls
&lt;/h2&gt;

&lt;p&gt;Same character, two new scenes, fresh prompts.&lt;/p&gt;

&lt;p&gt;High-level identity held everywhere. Hair, eyes and the main colors survived without effort. The fine-grained state did not. In both new scenes the camera sat behind the character, and the entire left and right assignment flipped: the mustard sleeve and the loops moved to the opposite side of the body. They stayed on the side nearest the camera, which is where they had been in the original.&lt;/p&gt;

&lt;p&gt;If you are generating a comic or a character sheet where handedness matters, that is a real constraint, and you will never see it with a symmetrical design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 3, reference input versus full description
&lt;/h2&gt;

&lt;p&gt;Same scene, same seed, two runs. First with the full written description. Second with the description deleted and the earlier image attached as a reference at default strength.&lt;/p&gt;

&lt;p&gt;The reference carried hair, eyes and the main colors with zero description, which is a genuine reduction in prompt length. It dropped the color break at the elbow, so both sleeves came back plain. The loops multiplied.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj3z0a5preuoboasxom3t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj3z0a5preuoboasxom3t.jpg" alt=" " width="800" height="859"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Large flat regions transfer. Small structural information does not. That split repeated in every check where the character moved between generations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 4, edit versus regenerate
&lt;/h2&gt;

&lt;p&gt;One instruction: change the mustard layer to deep teal, keep everything else, with the preserved elements listed by name including the charcoal sleeve.&lt;/p&gt;

&lt;p&gt;The edit held the composition almost exactly and then turned both sleeves teal, erasing the element I had named in the preservation clause, and repainted the knee patch. The output also came back at a smaller resolution than the source.&lt;/p&gt;

&lt;p&gt;The control, the original prompt with one word changed and generated fresh, kept every property correct across all four runs and produced a completely different composition.&lt;/p&gt;

&lt;p&gt;Regenerating behaved as the method predicts. The edit is the interesting half, because it decides whether you can fix an artifact you already like without losing the parts that made it worth keeping.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means if you are evaluating a platform
&lt;/h2&gt;

&lt;p&gt;Treat the evaluation like testing an unreliable dependency. Assert on properties, not on vibes. Run every assertion twice. Pin the seed when you want to isolate a variable and release it when you want to sample the distribution. Count things instead of eyeballing them, and pick a fixture where counting is possible.&lt;/p&gt;

&lt;p&gt;I ran all of this on &lt;a href="https://eap.pixai.art/go/balazs2" rel="noopener noreferrer"&gt;Tsubaki.3&lt;/a&gt; on PixAI, which is anime focused and exposes models, LoRAs, reference input and instruction editing in one panel. The platform's &lt;a href="https://blog.pixai.art/en/sdxl-anime-models-pixai-guide/" rel="noopener noreferrer"&gt;SDXL model guide&lt;/a&gt; covers why the older model family behaves differently on prompt syntax, which matters if you plan to mix families.&lt;/p&gt;

&lt;p&gt;The numbers above are that platform's numbers. The method is portable, and it takes an afternoon.&lt;/p&gt;

&lt;p&gt;If you want to run it, &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;start here&lt;/a&gt; and design your fixture with one asymmetric property. That single detail will tell you more than any gallery of cherry-picked samples.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>Chaining Image Generations Is a Pipeline Bug: Measuring Drift Across Four Rendering Stages</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Wed, 09 Sep 2026 12:07:16 +0000</pubDate>
      <link>https://dev.to/merl985/chaining-image-generations-is-a-pipeline-bug-measuring-drift-across-four-rendering-stages-4ioj</link>
      <guid>https://dev.to/merl985/chaining-image-generations-is-a-pipeline-bug-measuring-drift-across-four-rendering-stages-4ioj</guid>
      <description>&lt;p&gt;If you have ever built a data pipeline where each step consumes the previous step's output, you already know the failure mode: an error introduced at step two arrives at step five looking exactly like a legitimate value. Downstream, both look like ordinary values of the same type.&lt;/p&gt;

&lt;p&gt;Image generation pipelines behave the same way, and I measured it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;The subject is one drawing of an ice sculptor beside a block of ice with a thermos frozen inside it. Four rendering stages, run on Tsubaki.3 in PixAI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;line art -&amp;gt; grayscale -&amp;gt; flat colors -&amp;gt; final render
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every run held these constant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;same seed&lt;/li&gt;
&lt;li&gt;same model, no style preset, Pro mode&lt;/li&gt;
&lt;li&gt;one image in the Base Image slot&lt;/li&gt;
&lt;li&gt;Single generation, no batch, so the measurement reflects instruction following rather than best of four&lt;/li&gt;
&lt;li&gt;same instruction shape: one sentence naming the stage, one clause listing what stays fixed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Six identifying details were declared up front, chosen to be asymmetric or countable so that survival is checkable rather than arguable: a braid behind the left ear, a badge on the left collar, four tools on the belt, one glove on the left hand, one sleeve rolled and one down, and the thermos inside the ice.&lt;/p&gt;

&lt;p&gt;Loading a base image changes the output size without changing the setting. Runs without a base image came back at 960 by 1280, and the identical setting with a base image loaded came back at 896 by 1184. Trust the size on the finished file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxi0delknzmwmkap0wkmp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxi0delknzmwmkap0wkmp.png" alt=" " width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What held
&lt;/h2&gt;

&lt;p&gt;Composition held almost exactly. Aligning edge maps against the line art, the largest displacement across every base-image run was six pixels on a frame 1,184 pixels tall. All six declared details and the camera angle came through every stage.&lt;/p&gt;

&lt;p&gt;Run the same finishing instruction directly from the line art, and edge overlap against the original scores 0.168. Run it from the flat color stage instead, and it scores 0.147. Drop the base image entirely and generate from the text alone, and it scores 0.083, with the composition sitting 31 pixels across and 28 down from where the line art put it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flgn7io95w08vjogu91ze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flgn7io95w08vjogu91ze.png" alt=" " width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What broke
&lt;/h2&gt;

&lt;p&gt;The chained final render preserved everything and advanced almost nothing.&lt;/p&gt;

&lt;p&gt;Measured on the ice surface, the share of pixels sitting on a hard edge went from 15.8 percent at the flat color stage to 24.7 percent after the render instruction. A finishing pass should be moving in the other direction. The same instruction run directly from the line art brought that share to 3.7 percent, and the ice came back translucent.&lt;/p&gt;

&lt;p&gt;In an empty patch of white background, the tonal range ran zero in the line art, two in the grayscale, two in the flat colors, then 52 after the chained render step, filled with a blocky mosaic. That pattern was already present at stage two, sitting at an amplitude too low to see. Four passes later it was the most visible thing in the frame. The direct render, from the same prompt text, left the same patch at a range of one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the topology matters
&lt;/h2&gt;

&lt;p&gt;At stage three the model gave the thermos a pale wood handle. My prompt says nothing about a handle color. At stage four that handle arrived unchanged, in the same shape and the same tone, because by then it was pixels in the input image exactly like everything I had specified.&lt;/p&gt;

&lt;p&gt;Each pass behaves as though its input image is the whole story. Chaining therefore promotes every intermediate guess to a fact, and on this evidence the later passes had nothing to separate an instruction from an earlier guess.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3mtejsxftbcqkyuotrmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3mtejsxftbcqkyuotrmg.png" alt=" " width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Across three renders started from the line art rather than the chain, that handle came out dark red once and grey metal twice. Pale wood appeared in none of them. The two chained stages matched each other exactly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The refactor
&lt;/h2&gt;

&lt;p&gt;Hold the structural base fixed and generate every treatment from it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 +-&amp;gt; final render
line art (base) -+-&amp;gt; warm sunset
                 +-&amp;gt; cool moonlight
                 +-&amp;gt; strong backlight
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drift stops compounding, because every step reads the same fixed input. The cost is real: a direct render has no access to the intermediate information, so it reinvents anything the middle stages had settled. In my runs the direct version produced the better finish and dropped details the chain had locked in. From one instruction you get one of the two.&lt;/p&gt;

&lt;p&gt;That is the configuration behind the four finishes here, one per lighting condition, with only the light changed between them. Composition held in all four, shadows followed the named source, and the stated local colors kept their hue under colored light in three of the four. Under moonlight the warm bias on the stone wall fell from 23 points of red over blue to under one, which is the one case where the light repainted the surface instead of lighting it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Treat the earliest artifact that carries the structure as the source of truth, and read from it every time.&lt;/li&gt;
&lt;li&gt;Chaining generations is convenient and lossy. Every pass rewrites the entire image, so anything that survives does so by being redrawn the same way.&lt;/li&gt;
&lt;li&gt;Lock the seed and change one input at a time, or you cannot attribute any difference you observe.&lt;/li&gt;
&lt;li&gt;Declare your checkable details before the run. Asymmetric and countable beats descriptive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of the above comes from single generations rather than repeated trials, so treat the direction as the finding and the exact numbers as one sample.&lt;/p&gt;

&lt;p&gt;If you want to run the same experiment on a drawing of your own, the model I used is on &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;PixAI&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>29 Words on One Locked Seed, and What They Cost the Picture Underneath</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Tue, 08 Sep 2026 08:16:56 +0000</pubDate>
      <link>https://dev.to/merl985/29-words-on-one-locked-seed-and-what-they-cost-the-picture-underneath-2l5a</link>
      <guid>https://dev.to/merl985/29-words-on-one-locked-seed-and-what-they-cost-the-picture-underneath-2l5a</guid>
      <description>&lt;p&gt;Every guide on getting text into AI-generated images says the same thing: keep it short, keep it big, and hope. That is folk wisdom, and folk wisdom is what you get when nobody isolates the variables.&lt;/p&gt;

&lt;p&gt;So I isolated them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;Think of a text-to-image call as a function with a lot of arguments, most of which nobody holds constant when they benchmark it. Model, seed, aspect ratio, subject description, style, and the actual text instruction all move at once in a typical comparison, and then somebody publishes a conclusion about text rendering.&lt;/p&gt;

&lt;p&gt;My setup pinned everything except one argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generate(
  model:    "Tsubaki.3",          // fixed
  seed:      &amp;lt;locked&amp;gt;,            // fixed, identical on every run
  ratio:    "3:4",                // fixed
  subject:   &amp;lt;one paragraph&amp;gt;,     // fixed, reused verbatim
  style:     none,                // no preset, no LoRA
  batch:     1,                   // single generation, never best-of-four
  text:      &amp;lt;THE ONLY VARIABLE&amp;gt;
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last constraint matters more than it looks. Generating four and picking the nicest one measures your fourth attempt, not the model's instruction following. Every result below is a first and only run.&lt;/p&gt;

&lt;p&gt;I also ran a control with the &lt;code&gt;text&lt;/code&gt; argument empty, which turned out to be the most informative run of the whole set.&lt;/p&gt;

&lt;p&gt;The subject was a woman in her fifties repairing box kites on a coastal dune, carrying four checkable details: short grey hair, goggles on her forehead, a brown patch on the right hip of her apron, and a spool of orange cord on her left forearm. Countable features give you a diff target.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 1: two text elements
&lt;/h2&gt;

&lt;p&gt;A title and a subtitle, requested in large capitals in the empty sky at the top.&lt;/p&gt;

&lt;p&gt;Both correct. Title cap height 163 pixels, subtitle 31, clean gap between them, nothing overlapping the character.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 2: five text elements
&lt;/h2&gt;

&lt;p&gt;Title, tagline, date, a two-line information block, and a corner badge, in one call. I chose the strings so no word repeated anywhere on the poster, which gives you traceability: every rendered string maps to exactly one instruction.&lt;/p&gt;

&lt;p&gt;All five elements appeared in the requested positions. Four were correct. The fifth was a small corner block where &lt;code&gt;NINE&lt;/code&gt; rendered as &lt;code&gt;NIVE&lt;/code&gt;, while &lt;code&gt;NORTH DUNE&lt;/code&gt; on the line beneath it came out right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feihany0s63a4b7tchcgx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feihany0s63a4b7tchcgx.jpg" alt=" " width="799" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The hierarchy is the interesting part, because it is measurable rather than a matter of taste. Cap heights, top to bottom:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Element&lt;/th&gt;
&lt;th&gt;Cap height&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Title&lt;/td&gt;
&lt;td&gt;164 px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tagline&lt;/td&gt;
&lt;td&gt;31 px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;22 px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Badge&lt;/td&gt;
&lt;td&gt;~18 px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Info line 2&lt;/td&gt;
&lt;td&gt;17 px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Info line 1&lt;/td&gt;
&lt;td&gt;15 px&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That ordering matches the importance I assigned each element in the prompt. I never specified a single size. The model inferred the ranking from the semantic role of each string, which is useful behavior if you are generating a lot of layouts.&lt;/p&gt;

&lt;p&gt;Note where the error landed: the 15 pixel line, the smallest thing on the poster. Two pixels separate it from the correct line directly below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 3: swap the script, hold everything else
&lt;/h2&gt;

&lt;p&gt;Same seed, same position, same instruction shape, comparable title length. Only the writing system changed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Latin: correct&lt;/li&gt;
&lt;li&gt;Japanese (3 characters, kanji plus hiragana): correct&lt;/li&gt;
&lt;li&gt;Korean (4 Hangul blocks): 1 of 4 blocks correct&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxeb6mi561qrpsl5uubqv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxeb6mi561qrpsl5uubqv.jpg" alt=" " width="800" height="665"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Korean failure mode is the one to internalize. All four blocks are valid, well formed Hangul syllables. Spacing is even. Stroke weight is consistent. The output looks completely correct and says the wrong thing.&lt;/p&gt;

&lt;p&gt;This is the difference between a crash and silent data corruption, and it has the same implication: you cannot validate this by looking at it, only by having someone read it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 4: relational layout instructions
&lt;/h2&gt;

&lt;p&gt;Three simultaneous position constraints in one prompt, expressed relative to the subject rather than to the canvas: title above her head, date in the lower left, badge in the upper right, all text clear of her face and the kite.&lt;/p&gt;

&lt;p&gt;Then the same prompt with one addition: reserve the top third as empty sky.&lt;/p&gt;

&lt;p&gt;Run A honored all three positions and put a lowercase &lt;code&gt;i&lt;/code&gt; in the middle of an all-capital title, plus a small non-letter mark after the final D.&lt;/p&gt;

&lt;p&gt;Run B produced every word correctly and solved the reservation by building something I never asked for: a solid header strip across the top 23.7 percent of the frame with the title set inside it. Her head starts at 34.8 percent, the kite at 36.2, both below the band as requested. The badge left its assigned corner and attached itself to the end of the title.&lt;/p&gt;

&lt;p&gt;Across both runs: 15 element position requests, 14 honored.&lt;/p&gt;

&lt;h2&gt;
  
  
  The finding nobody benchmarks
&lt;/h2&gt;

&lt;p&gt;Here is why the empty control run mattered. I measured the vertical position of the top of the character's head as a fraction of frame height:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;Head position&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Control, no text&lt;/td&gt;
&lt;td&gt;25.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layout run A&lt;/td&gt;
&lt;td&gt;28.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Japanese&lt;/td&gt;
&lt;td&gt;33.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Five elements&lt;/td&gt;
&lt;td&gt;34.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Korean&lt;/td&gt;
&lt;td&gt;34.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layout run B&lt;/td&gt;
&lt;td&gt;34.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two elements&lt;/td&gt;
&lt;td&gt;35.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Same seed on every row. Every run carrying text pushed the subject lower and made it smaller, by 2.5 to 9.3 percentage points.&lt;/p&gt;

&lt;p&gt;The text is not composited over a finished illustration. It is drawn in the same pass, out of the same frame budget, and the artwork is what gets compressed to make room. In run B a quarter of the output stopped being a picture entirely.&lt;/p&gt;

&lt;p&gt;If you are generating assets programmatically, this is a real constraint on your pipeline: you cannot add a text argument and expect the visual to stay put, and you cannot fix a bad string with a retry without rebuilding the composition around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aggregate results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;29 Latin words requested, 27 rendered exactly&lt;/li&gt;
&lt;li&gt;2 failures: one wrong letter, one case defect&lt;/li&gt;
&lt;li&gt;Large display type: correct in 100% of runs&lt;/li&gt;
&lt;li&gt;Both failures at small size or under heavy layout constraints&lt;/li&gt;
&lt;li&gt;Japanese correct, Korean 1 of 4 blocks&lt;/li&gt;
&lt;li&gt;15 position requests, 14 honored&lt;/li&gt;
&lt;li&gt;Hierarchy correctly ranked in every layout, unprompted&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I would ship
&lt;/h2&gt;

&lt;p&gt;Generate the composition and the headline together, since that is where the model is strong and where it does work you would otherwise do by hand. Treat every returned string as untrusted input and read it character by character. Set fine print, dates, prices, and anything legally fixed in an editor afterward. And never ship a script you cannot read without a human check, because the failure mode there is invisible.&lt;/p&gt;

&lt;p&gt;Short display text is close to solved. Everything below about 20 pixels of cap height is still yours to handle.&lt;/p&gt;

&lt;p&gt;You can run the same test on your own character at &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;https://eap.pixai.art/go/balazs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>One Reference Image, Eight Character Sheet Runs, and What the Model Made Up</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Tue, 01 Sep 2026 17:48:55 +0000</pubDate>
      <link>https://dev.to/merl985/one-reference-image-eight-character-sheet-runs-and-what-the-model-made-up-1h7p</link>
      <guid>https://dev.to/merl985/one-reference-image-eight-character-sheet-runs-and-what-the-model-made-up-1h7p</guid>
      <description>&lt;p&gt;Character sheets are a reference format. Front, side, and back views, a range of expressions, a set of poses, enough detail that another person could work from the sheet without asking you questions.&lt;/p&gt;

&lt;p&gt;The interesting engineering question is what happens when the input is underspecified. One image of a character does not contain the back of the coat. It does not contain the object hanging off a strap that runs behind the hip. Ask a model to expand that image into a full sheet, and it has to produce values for fields that were never set.&lt;/p&gt;

&lt;p&gt;So I ran it as a controlled test on &lt;a href="https://eap.pixai.art/go/balazs2" rel="noopener noreferrer"&gt;Tsubaki.3&lt;/a&gt;, the model PixAI currently has in early access, and measured what came back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test setup
&lt;/h2&gt;

&lt;p&gt;One original character, generated once from text, then used as the only reference for every run after it. Eight generations: a turnaround, the same turnaround again on a different seed, a third with one sentence added, a six-panel expression sheet, a nine-panel expression sheet, a four-pose sheet, a single pose, and an outfit sheet.&lt;/p&gt;

&lt;p&gt;Every setting held constant across runs: style preset off, Pro mode, Prompt Helper off, default negative prompt untouched, square format, one reference image attached.&lt;/p&gt;

&lt;p&gt;The character design is the instrument, and it splits into three groups.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAMED IN EVERY PROMPT      hair length and color, eye color,
                           red scarf, olive coat over grey sweater

REFERENCE ONLY             which side the hair tucks behind the ear,
                           which side the scarf tail hangs on,
                           strap across the chest with a metal slider,
                           notebook in the left chest pocket

ABSENT FROM THE REFERENCE  the back of the coat
                           the object on the end of the strap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first group is the control. If those drift, nothing else is worth reading. They did not drift in any of the eight runs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs2o668mfszzyz3msyodw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs2o668mfszzyz3msyodw.jpg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Result 1: silence is deterministic, promises are not
&lt;/h2&gt;

&lt;p&gt;The turnaround came back with three genuine views at a matched scale: 983, 978, and 978 pixels tall in a 1024 pixel frame. The back view had to be invented, since the reference never showed it. It came out as a plain quilted panel with a center seam.&lt;/p&gt;

&lt;p&gt;Then I ran the identical prompt, byte for byte, on a different seed. Same invented back. Same center seam.&lt;/p&gt;

&lt;p&gt;That is the useful finding. An unset field gets a default, and the default is stable enough to rely on.&lt;/p&gt;

&lt;p&gt;The strap behaves differently. The reference shows it crossing the chest and running to something behind the hip. Both turnaround runs dropped it entirely from the back view rather than resolving it, on two different seeds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffq4ivwehvhpoyb8ppdi6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffq4ivwehvhpoyb8ppdi6.jpg" alt=" " width="800" height="779"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the third run, I held the first run's seed and appended one sentence naming the bag. The bag appeared, correct material, correct hip. Two things came with it: a second strap crossing the first on the back, which no single shoulder bag produces, and the disappearance of the strap from the front and side views of that same sheet.&lt;/p&gt;

&lt;p&gt;One added constraint, satisfied at the point of the constraint, paid for elsewhere in the same output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Result 2: panel count is a real budget
&lt;/h2&gt;

&lt;p&gt;Six expressions in a two-by-three grid was the strongest output in the set. All six visually distinct, the face measuring between 243 and 260 pixels wide across the panels, and a metal slider a few pixels across surviving at roughly 341 by 512 pixels per portrait.&lt;/p&gt;

&lt;p&gt;Nine expressions in a three by three grid did something I did not predict. The faces stayed on model. The framing simplified: every panel squared up to the camera, the hair fell symmetrically, and a reference-only detail that held through all six panels of the smaller sheet vanished from all nine of the larger one. Two emotion pairs also converged, so nine slots produced seven clearly separate faces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Result 3: the sheet format itself costs resolution
&lt;/h2&gt;

&lt;p&gt;The pose sheet held proportions and broke layout. Four requested poses produced three distinct ones, and the crouching figure landed in the gap between two others at a different camera height instead of on the row.&lt;/p&gt;

&lt;p&gt;More useful was running the same crouch as a single figure in the full frame. The notebook in the chest pocket renders at 71 pixels wide there against 32 on the sheet, with the cover, page block and spine thickness all readable. The reaching hand resolved into five separated fingers.&lt;/p&gt;

&lt;p&gt;A quarter of a 1024 pixel frame has no room for that. The sheet was not failing at drawing; it was failing at budget.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiynma9kgn4w2aivnywk1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiynma9kgn4w2aivnywk1.jpg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What survived, ranked
&lt;/h2&gt;

&lt;p&gt;Across every figure, the reference-only details came out in a clear order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;notebook in the chest pocket   25 of 26 figures wearing the coat
strap across the chest         23 of 26 front and side views
scarf tail on one side         10 of 17 full body figures
hair tucked behind one ear     14 of 26 views that face the viewer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ordering is not random. The notebook is a high-contrast object in a fixed place on the garment, and every format keeps that place in frame. The strap depends on which side of the body is visible. The hair parting has no object holding it, so it goes first.&lt;/p&gt;

&lt;p&gt;One caveat that cuts across all of it. The notebook and the strap are missing from the outfit sheet completely, because the coat they live on was replaced. Identity carried by an object lasts exactly as long as the object does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways if you try this
&lt;/h2&gt;

&lt;p&gt;Design for the format. Put the identifying details on objects, keep those objects on a garment you plan to keep, and treat anything that lives purely in the silhouette as the first thing you will lose.&lt;/p&gt;

&lt;p&gt;Run the turnaround twice before you trust the back. The second run tells you whether the invented answer is a stable default or a coin flip.&lt;/p&gt;

&lt;p&gt;If a detail matters, generate it as a single image rather than a panel. The overview and the detail are different jobs.&lt;/p&gt;

&lt;p&gt;One last thing. Treat the output as a working reference rather than a production model sheet. Everything on it that your original image never showed is a plausible guess, which is a different thing from correct.&lt;/p&gt;

&lt;p&gt;If you have one good picture of your OC sitting in a folder, the whole experiment costs you a few generations. &lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;Try it on PixAI&lt;/a&gt; and see which of your character's details are carried by an object and which are carried by luck.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
    <item>
      <title>Adding an Instruction Moved the Bug Instead of Fixing It</title>
      <dc:creator>Merl Merl</dc:creator>
      <pubDate>Mon, 31 Aug 2026 19:35:52 +0000</pubDate>
      <link>https://dev.to/merl985/adding-an-instruction-moved-the-bug-instead-of-fixing-it-1m90</link>
      <guid>https://dev.to/merl985/adding-an-instruction-moved-the-bug-instead-of-fixing-it-1m90</guid>
      <description>&lt;p&gt;Image models fail in a way that is hard to debug: the output looks fine. There is no stack trace, no assertion error, just a picture that is plausible and quietly different from what you asked for.&lt;/p&gt;

&lt;p&gt;So I built a test fixture and ran nine controlled generations against it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fixture
&lt;/h2&gt;

&lt;p&gt;One scene, described in exactly the same words in every prompt, with four objects placed so that I could check each one afterwards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- red toolbox      -&amp;gt; viewer's left of the character
- metal ladder     -&amp;gt; viewer's right of the character
- ticket booth     -&amp;gt; further back, behind the wheel
- the character    -&amp;gt; standing at the foot of the Ferris wheel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model under test was &lt;a href="https://eap.pixai.art/go/balazs2" rel="noopener noreferrer"&gt;Tsubaki.3&lt;/a&gt; on PixAI. Two rules kept the runs comparable. Only the camera sentence changed between prompts, and it came first, since these models read a prompt roughly in order of importance. Every test ran as a single generation instead of a batch, because selecting the best of four measures what the model can produce on the fourth attempt, which is a different question.&lt;/p&gt;

&lt;h2&gt;
  
  
  The baseline
&lt;/h2&gt;

&lt;p&gt;The first prompt named no camera at all, and I ran it four times. All four came back the same way: eye level, character centered, full body, wheel behind him at roughly equal width on both sides.&lt;/p&gt;

&lt;p&gt;The left and right assignments held in all four images. The booth, described as standing behind the wheel, ended up beside it every time. That split showed up in every later run too, so it is worth stating early: &lt;strong&gt;left and right are properties of the frame, behind is a property of the camera&lt;/strong&gt;, and only one of those two moves when the lens does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 1: camera height
&lt;/h2&gt;

&lt;p&gt;Two prompts, identical except for one sentence. One asked for an extreme low angle with the camera almost on the concrete, the other for a bird's-eye view from the top of the wheel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjxorx4e84wzd0vzmg4za.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjxorx4e84wzd0vzmg4za.jpg" alt=" " width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both moved the lens instead of bending the pose. Boots large and close, horizon low, base legs splaying outward in the first. Hard hat crown dominant, legs foreshortened, structural shadows consistent with the viewpoint in the second.&lt;/p&gt;

&lt;p&gt;The failure here is partial. In the low-angle run, the steel base directly behind the character reacted to the new viewpoint, while the wheel itself stayed a clean frontal circle with evenly spaced spokes, exactly as it looked at eye level. In the high-angle run, the same wheel turned correctly, its rim running out of both sides of the frame as two curves. Near geometry followed the camera, while distant geometry sometimes kept the view it already had.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 2: the regression
&lt;/h2&gt;

&lt;p&gt;The depth prompt asked for three layers: toolbox very close to the lens, character in the middle distance beside the ladder, booth far behind him and much smaller than he is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdzkcbvkpzw9ewift6rp5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdzkcbvkpzw9ewift6rp5.jpg" alt=" " width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Result of run one:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assertion&lt;/th&gt;
&lt;th&gt;Outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;toolbox in the immediate foreground, large&lt;/td&gt;
&lt;td&gt;pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;character readable in the middle distance&lt;/td&gt;
&lt;td&gt;pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;booth far back, much smaller than him&lt;/td&gt;
&lt;td&gt;pass, around 40 percent of his height&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;character stands beside the ladder&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;fail&lt;/strong&gt;, ladder moved to the booth&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One failing assertion, so I patched the prompt. I added two phrases and changed nothing else: the booth got a frame position, near the right edge of the frame, and the character got one too, in the center of the frame.&lt;/p&gt;

&lt;p&gt;Result of run two:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assertion&lt;/th&gt;
&lt;th&gt;Outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;character stands beside the ladder&lt;/td&gt;
&lt;td&gt;pass, fixed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;booth near the right edge of the frame&lt;/td&gt;
&lt;td&gt;pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;booth far back, half his height&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;fail&lt;/strong&gt;, around 110 percent of his height&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;character in the center of the frame&lt;/td&gt;
&lt;td&gt;partial, sits right of the center line&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The patch fixed the failing assertion and broke a passing one. The booth moved to the right edge as instructed and came forward while doing it, its awning now above the character's hard hat. Two runs of the same scene, two different failure profiles, and the second was not obviously better than the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 3: the lens is a separate control
&lt;/h2&gt;

&lt;p&gt;Fisheye has two parts. The lens has to bend the image, and the camera has to be somewhere specific for the bend to make sense. I asked for both: a fisheye shot from directly beneath the wheel looking straight up.&lt;/p&gt;

&lt;p&gt;The distortion arrived, and it is convincing, with the concrete apron bowing into a wide arc. The camera position was ignored, and what came back has two viewpoints in one frame. The character is drawn from above, crown of the hard hat toward the lens, legs foreshortened, shadow pooled beneath him. The wheel behind him is drawn from below, base legs splaying downward, top edge tilting away.&lt;/p&gt;

&lt;p&gt;The lens effect applied to the whole frame, while the camera position resolved separately for the figure and for the structure behind him.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test 4: five constraints in one prompt
&lt;/h2&gt;

&lt;p&gt;The last prompt stacked five requirements: low camera, toolbox in the immediate foreground on the viewer's left, character in the middle distance climbing the ladder with his back to the camera, an older man in a green coverall further back on the viewer's right holding a clipboard and looking up, wheel filling the background.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7uron0bbwr5p4xqbrdmm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7uron0bbwr5p4xqbrdmm.jpg" alt=" " width="768" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All five landed, including the back-turned pose, which I expected to be the weak point since turning a character away removes the face.&lt;/p&gt;

&lt;p&gt;The busiest prompt in the test produced the cleanest result. The wording difference is that every element here carried a frame side alongside its distance, while the depth prompt named only layers. Whether the frame side is what carried the result, two runs cannot tell me.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the nine runs support
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Side of the frame:&lt;/strong&gt; honored in every run where it appeared, including ground level, overhead, and fisheye.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Camera height:&lt;/strong&gt; three clear results out of four, with the overhead run understating the distance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lens distortion:&lt;/strong&gt; present in both runs that asked for it, independent of camera position.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Depth, near layer:&lt;/strong&gt; landed in all three prompts that asked for one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Depth, far layer:&lt;/strong&gt; correct in two runs, slid forward in the third.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size ratio between two objects:&lt;/strong&gt; returned as written in neither of the two runs that asked for one. Much smaller than he is produced 40 percent; half his height produced 110 percent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The camera is controllable on this model. The spatial relationships between objects are not deterministic across runs of the same prompt, and adding instructions to fix one relocated the variance rather than eliminating it. If you are building a pipeline on top of this, treat camera position as a parameter and object-to-object geometry as something you verify per output.&lt;/p&gt;

&lt;p&gt;If you want to run the same experiment, the method is cheap: fix three or four nameable objects in your scene, write down where each one belongs, change one sentence per run, and check the output against your list instead of against your impression of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eap.pixai.art/go/balazs" rel="noopener noreferrer"&gt;Try your own composition challenge on PixAI&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>design</category>
    </item>
  </channel>
</rss>
