模組三|AI 生圖與生片產線(Day 10–19)
昨天講三條產線怎麼分工。今天講其中一條的核心手法,也是這整個模組最值得帶走的一招。
先講我失敗的兩個版本,因為解法只有對照著失敗才看得懂。
需求很單純:
第二點和第三點是不同的問題,而我一開始沒有分清楚。
最直覺的做法。把畫風寫進 prompt,把角色寫進 prompt,一起送出去。
結果:跨視角不一致。
同一次生成裡,正面是這個人,側面就變成另一個人了。因為模型並不真的理解「這三個視角是同一個對象」,它只是在畫三個符合描述的東西。
這一版直接作廢。

第二版學聰明了:既然文字不夠,那就附參考圖。
每個角色本來就有立繪(角色卡圖),所以我讓每個角色用自己的卡圖當參考去生三視圖。
結果:角色對了,但畫風跟著卡圖飄。
問題在於那 20 張卡圖本身畫風就不完全一致:它們是不同時間生的,光線、飽和度、線條粗細都有差異。
於是三視圖繼承了這些差異,而且被放大了。我用來修正的東西,本身就是誤差的來源。
這一版的教訓是:參考圖會把它身上所有的東西一起傳過去,不只是你想要的那個維度。
一張圖同時攜帶:畫風、角色、服裝、配色、構圖、光線。你附上去的時候,這六個維度全部一起生效。
第三版的做法是這樣。
先選一張圖當風格錨,全部 20 個角色都用同一張:
STYLE_REF="assets/char-tuner.png"
然後 prompt 這樣寫(這是實際在跑的版本):
Use the attached image ONLY as an art style reference for rendering technique:
flat cel-shaded stylized painterly anime, clean crisp lineart, bold flat shading,
BRIGHT high-key luminous lighting, airy, NOT photorealistic, NOT a 3D render.
IGNORE the reference image's character, outfit, colors and composition completely.
翻成白話:這張圖我只要它的渲染技法。它的角色、服裝、配色、構圖,全部忽略。
角色資訊則完全由文字提供:
The character: $desc
$desc 從那個角色自己的 prompt 檔讀進來。

因為它把六個維度拆成兩條通道:
| 維度 | 走哪條通道 | 為什麼 |
|---|---|---|
| 畫風、渲染技法、光線 | 圖片(固定不變) | 這些用文字描述不穩定,但用圖示範很準 |
| 角色、服裝、配色、構圖 | 文字(每次不同) | 這些需要每個角色不一樣 |
而關鍵在於:圖片那條通道是固定的。
20 個角色用同一張錨圖,所以畫風在構造上就一致,不是靠模型努力保持一致,是因為輸入根本沒變。
版本二的問題就在這裡:參考圖每次都換,畫風當然每次都不一樣。
有人可能會問:既然只用一張圖,那不寫 IGNORE 那句會怎樣?
會出現一堆調律者的殘影。錨圖是調律者的立繪,如果不明確排除,模型會把他的髮色、服裝、站姿一起帶進每一個角色。
參考圖的預設行為是「全部參考」,你必須明確關掉不要的部分。
這件事的形狀,工程師應該覺得眼熟:
import * 會把整個模組的東西全部拉進來,你得改成具名 import共同點是:預設是全盤繼承,而你要的通常只是其中一部分。 差別只在於這裡的「明確排除」是用自然語言寫的。
還有一個細節值得單獨講,我是在寫這篇時回頭比對舊版才注意到的。
舊版的風格段,是靠指名一部商業作品來描述畫風的:「用某某作品的畫風」這種寫法。
新版換成了純描述:
flat cel-shaded stylized painterly anime, clean crisp lineart, bold flat shading,
BRIGHT high-key luminous lighting, airy, NOT photorealistic, NOT a 3D render
同樣的畫風,但拆成了七個可以獨立調整的維度:上色方式、線條、陰影、亮度、空氣感,以及兩個否定條件。
這個轉換的價值不只在合規(雖然那也很重要):
| 指名作品 | 描述維度 | |
|---|---|---|
| 你知道自己要了什麼嗎 | 不知道,那是個黑盒 | 知道,七個維度列在那裡 |
| 想調亮一點 | 沒辦法,只能整包換 | 改 BRIGHT high-key 那一項 |
| 換一個模型還能用嗎 | 不一定,看它認不認得這個名字 | 可以,描述詞是通用的 |
指名是引用,描述是規格。
而且我後來才發現一個副作用:現行腳本讀角色 prompt 檔時是從第二段開始讀的:
desc=$(... | awk -v RS='' 'NR>=2{print; print ""}')
第一段(舊版那個指名式的風格段)根本沒被送出去。 它還躺在檔案裡,但已經是死的了。
我做這個重構的動機是解決畫風漂移,順手把對商業作品的依賴也一起砍掉了,當時完全不是為了這個。
上面那套「固定風格錨、忽略角色」是拿來量產角色三視圖的:我要二十個不同角色共用同一套渲染規格,角色外觀由各自的文字資料提供。
後來做短篇單回插圖的時候,任務剛好相反:調律者與綠語都已經有定稿立繪,我要的不是新設計,而是讓讀者一眼認出同一個人。
這次我附上兩張既有 key art,並且在 prompt 的第一行先替它們定角色:
Use the attached character key art to lock canonical identity, costume and rendering quality.
Do not copy the reference composition or background.
不是「請參考這兩張圖」,而是三個可驗收的責任:
| 參考圖負責 | prompt 必須明寫 | 不准繼承 |
|---|---|---|
| 身分 | 髮色、髮型、是否人類/義體 | 原本的站姿與表情 |
| 服裝 | 白色長醫療外套、層疊青白裙、耳機與工作外套 | 原本的背景與道具 |
| 渲染品質 | 光澤動畫質感、白色裝甲的高光與面板線 | 原本的構圖 |
接著才寫這一回獨有的畫面關係:綠語的手掌隔開探針與晶片、晶片獨自放在香案外側,以及香頭立刻分成兩道、全程不交會的白煙。
而是把參考圖的用途和驗收拆開。
我先把全景限制成 兩名完整前景角色,每人各有一張 key art;焰刃與霜瞳只作霧中的遠景守衛。
這不是因為四人版的描述不夠長。同一張圖我先前走 API 產線試過四人同框,出現過「霜瞳變成第二個焰刃」以及「綠語複製兩份、霜瞳消失」——模型不會報錯,它會漏掉一個角色,然後拿另一張參考圖去填補那個位置。
四個角色配四張重型參考圖,超過了這次任務能穩定維持的辨識負荷。 這是輸入量的問題,不是描述精度的問題,所以把 prompt 寫得更長沒有用。
所以成品的驗收不是只看「畫得好不好看」,而是逐條勾:
這張圖最後通過的是「兩張 key art + 少量角色 + 場景專屬驗收」這個組合,而不是某個更長的萬用 prompt。
04.01 過關後,我沒有把它當成一次幸運命中,而是用同一條契約接著產出 04.02 到 04.10,合計九張 1536×1024 的短篇插圖。每一回都只替當下的關係衝突選兩名完整前景角色:例如綠語與零式對照被改寫的記錄、調律者與零式用拔下的控制接頭建立界線、焰刃把空白牌放回第五格。
其他隊員不是被遺忘,而是依劇情降成遠景守衛、局部或完全不入鏡。這讓我可以把模型的辨識預算留給讀者真正要讀的手、道具與關係,而不是拿來湊一張四人合照。
流程沒有因此變成「按一次就全過」。04.10 的第一張有不必要的遠景人影,雖然主角和第五格都正確,仍違反了我自己訂的畫面限制。我沒有把它算作可用成品,而是只針對「畫面只能有兩人」重生;第二張才收斂成焰刃、零式、空白牌與第五格四個讀點。
這次的可複製做法不是保存九段 prompt,而是每回都先回答四個問題:
把第四題寫在送出前,人工審圖才不會變成「好看就算過」。
接著我把這條流程帶到第 5 篇的 05.01 到 05.10:十張 1536×1024 插圖全數插回短篇閱讀器。這一輪不是單純重複第 4 篇,因為阿樹在 05.03 正面進場。
這時候「沿用前一張看起來差不多的角色圖」反而是風險。我先把他的現行 key art 和三視圖當成新的身分基準:捲袖白襯衫、深色長褲、腕上的舊繩,以及只在輪廓邊緣出現的淡青掃描裂邊。接著在 05.03、05.05 到 05.10 的 prompt 裡,把他明確限制成非戰鬥、無武器、非怪物;這些不是文案形容詞,而是檢查點。
第五篇也驗證了另一件事:角色表有六個人,不等於插圖該有六個完整人像。每一張仍只讓阿樹和當回關係動作的另一人完整入鏡——零式的關屏、綠語收回醫療霧、焰刃以刀背壓門、調律者停在肩上方的手。其他人只在遠景或不入鏡。這樣讀者仍看得出隊伍位置,模型卻不必在同一張圖同時維持六張臉、六套服裝和六個動作。
05.08 還提供了一個很小但有用的反例:首張把「最後一截斷香」錯畫成穿進香孔的繩。畫面氣氛沒有問題,事件卻錯了,所以我只重跑那一張,並把「細短未點燃香枝在手中」「不得有繩索或感應線接到香孔」升成硬性限制。最後留用的版本才真正表達「堵住門縫,而不是接回線路」。
這輪把驗收題目再多加兩條:
第 6 篇的 06.01 到 06.10 再跑十張,驗的是另一種錯誤:新角色很容易只剩下職業符號。鎮嵐的角色卡有金色編髮、琥珀警示燈、重盾工程語彙與機甲腿;這些只保證她看起來像守門者,還不保證她在故事裡是那個「把自己接成門燈、等最後一個人回來」的人。
所以 06.05 首次讓她完整入鏡時,我把「胸前接頭連著白燈」「避難所被褥全朝門口折好」「名冊最後一行空著」列為同級讀點。06.06 再把綠語的同意規則放進畫面:先問、只固定燒熱的接頭、不拔線,並讓白燈改由獨立備電供應。若只畫一名重裝角色加一盞燈,這段關係就會消失。
名冊則是另一個不能交給模型自由發揮的物件。06.07 到 06.10 需要表達「三十五與三十四不一致」「留一行給回來的人」,但我沒有要求模型畫出名字或數字;它只畫無文字的格槽、鐵板與一條刻意空著的槽。文字正確性不是這組插圖的任務,真正要驗收的是:空位是否可見、誰把它固定在門內、以及白燈是否已經不再消耗鎮嵐。
這輪再補兩條檢查:
第 7 篇的十張圖,牧械帶來的問題不是多一位人,而是一群機械。若每台小機械都當角色描述,畫面很快會變成失控的機甲合照;若只畫牧械,讀者又看不懂他「留線」究竟在留什麼。
我把小清潔機固定為低矮、單一指示燈的工具型同伴,其他機群則只用散開的低矮輪廓與遷徙路線表示。完整前景仍只留牧械與當回關係對象:焰刃扶正機器、綠語處理燙傷、零式對照無字線圖。07.09 的「半步」尤其要畫成可量的站位,不是寫在牌上的規則;07.10 則把假聲留在看不見的海霧裡,牧械只接雜訊線、不替它回答。
這讓群體仍有行為和方向,卻不讓模型被大量近景角色拖垮。新增的檢查題目是:群體在這張圖裡要讀的是每一張臉,還是它共同選出的路?
前面的重點沒有變:參考圖會全盤繼承,必須關掉不想要的維度。但現在我會把它寫得更精確:
| 任務 | 參考圖契約 |
|---|---|
| 量產不同角色的三視圖 | 固定風格錨;明令忽略錨圖的角色、服裝與構圖 |
| 已定稿角色的劇情插圖 | 每個前景角色各附一張 canonical key art;鎖身分、服裝與渲染品質;明令忽略原構圖與背景 |
| 人數超過模型能穩定分辨的上限 | 縮小完整角色數,其他人降成不可辨識的遠景或拆成下一張圖 |
不是「參考圖要不要用」,而是「這張圖在本次請求中被授權決定什麼」。 先寫清楚這份契約,才知道該把什麼交給圖、什麼留給文字、以及什麼必須在出圖後人工驗收。
代價一:錨圖選錯,20 個角色一起錯。
單點依賴。這張 char-tuner.png 現在是整套視覺的地基,如果它本身有什麼缺陷(比如飽和度偏高),那 20 個角色全部繼承。
而且換錨圖等於全部重生,成本是一整輪。
代價二:描述詞是靠試出來的,不是推導出來的。
那七個維度不是我分析出來的,是一次次調 prompt 慢慢收斂的。我沒辦法告訴你為什麼是這七個而不是九個。
它有效,但我不能保證它是最小充分集合。
代價三:文字通道還是有極限。
畫風走圖片、角色走文字之後,角色的外觀細節仍然只能靠文字描述,而文字描述複雜服裝的精度是有天花板的。
這就是為什麼後來還需要 Day 13 講的局部修圖——文字沒描述到位的地方,會生出多餘的東西。
代價四:這一版也是撞出來的。
我要再說一次,因為它是這個模組的實情:純文字(作廢)→ 卡圖當參考(畫風飄)→ 單一錨圖(定稿)。
兩次失敗,一次成功。 我寫的這些判準是事後的整理。
代價五:後面補的那條「key art 鎖身分」路線,把成本推到了人工驗收。
三視圖那條路是量產的,跑完看一眼就好。而劇情插圖這條路每一張都要逐條勾五個檢查點——服裝有沒有退化、角色有沒有被複製、道具的空隙有沒有守住。檢查點是人在看的,沒有腳本會叫。
而且它有一個硬上限:完整前景角色數。超過就得砍人或拆圖,這不是調 prompt 能繞過去的,等於在構圖階段就被綁住了。
我目前接受這個代價,因為劇情插圖一回只有一張;如果哪天要一天出十張,這條路就得換。
一、參考輸入會全盤繼承,你必須明確關掉不要的維度。
用參考圖、範本、既有設定當基礎的時候,先列清楚:這個東西身上有幾個維度?我要哪個?其他的怎麼關掉?
沒有列清楚的那些,會默默生效。
二、要固定的東西走「不變的通道」,要變的東西走「可變的通道」。
這是整篇最能搬走的一句。
不要讓「要一致的東西」也每次換一個來源,然後期待模型幫你保持一致。一致性應該是輸入的性質,不是輸出的運氣。
這條在別的地方也成立:測試的 fixture 要固定、build 的 base image 要 pin 住、快照比對的基準要單一。
三、用描述取代指名。
「做得像 X 那樣」是最快的溝通方式,也是最不可維護的規格。
判斷句:如果我想調整其中一個面向,我改得動嗎?
這條不只適用於 AI prompt。設計需求寫「做得像某某網站」、技術需求寫「做一個像某某產品的東西」——都會在實作階段炸開,因為沒有人知道那個名字實際包含哪些決定。
明天 Day 12,講這條產線的工程面:prompt 怎麼從程式碼裡搬出來變成資料。20 個角色、一角一檔,改設定不用碰腳本——以及一個從 Markdown code fence 抽內容的小約定,它讓 prompt 檔可以同時給人讀和給腳本讀。