iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0
AI Engineering

《矽墟》:我把一部科幻小說當成軟體專案來管系列 第 17

Day 17|我昨天答應給成本數字,今天給不出來

  • 分享至 

  • xImage
  •  

模組三|AI 生圖與生片產線(Day 10–19)

昨天那篇的最後一行寫著:明天講成本結算,這一整條產線實際花了多少。

今天我要說的是:我拿不到那個數字。

而且拿不到的原因不是我懶得查,是我昨天自己寫下的那行禁令擋住了。這篇就講這件事,以及一個沒有單價也能做的成本估算方式——那才是這一天真正能帶走的東西。

擋路的是我自己寫的一行字

昨天講的 bug 是:三視圖生成腳本的「已存在就跳過」比對的是中文檔名,成品早就改成英文了,所以重跑會把 20 個角色全部重生。實測 20/20 重生、0 skip。

我當時在 開發足跡.md 裡加了一行禁令:

未修前禁止事項:不得直接執行 bash gen_turnarounds.sh,包含為了取得成本數字而試跑。

「包含為了取得成本數字而試跑」——這半句是我自己補上去的,因為我當時就預料到會有今天這一刻。

要拿到「一輪全員三視圖重製實際花多少」,最直接的做法就是跑一輪然後看帳單。而跑一輪的意思,在 skip 失效的現在,就是 20 次 API 呼叫全額重來。

為了量成本而付出的成本,本身就是這篇要講的成本。

先回答昨天留的問題:修了沒

沒有。

我剛剛回去看了一次,gen_turnarounds.sh 第 27 行還是這樣:

if [ -f "$out" ]; then echo "skip $name (exists)"; continue; fi

out 仍然從中文的 prompt 檔名推導。昨天說的三個修法——建映射表、prompt 檔改英文、加 --dry-run 旗標——一個都還沒進去。

更難看的是這個:我回去查 git log,這支腳本在那之後確實被改過一次

2026-08-07  fix(turnarounds): locate prompt fences by heading instead of index

那次改的是另一個 bug——原本用「第 n 個程式碼圍欄」抓 prompt,只要有人在檔案中間插一節就會整批抓錯,改成用 H2 標題定位。是個好修法。

但我查了 skip 那一行最後一次被動是什麼時候:

2026-07-23  feat(novel, docs, assets): ...

我回到了同一支檔案,修了旁邊的東西,然後沒有碰它。

這比「一直沒空回去看」難堪得多。不是沒機會,是有機會而它不在我當下的注意力裡。

我把這件事寫出來,因為連載最容易出現的一種假象,就是文章裡承諾過的修法,讀者以為已經發生了。沒有就是沒有。

沒有單價,成本結構還是拆得開

單價拿不到,不代表這篇沒東西可寫。因為對個人創作者來說,真正會失控的從來不是單價,是次數。

這條產線的成本可以拆成三層:

內容 特性
一次性 風格錨定圖、prompt 模板、腳本本身 做一次,之後每輪都在用
每輪固定 20 個角色 × 1 次呼叫 角色數決定,一輪就是一輪
每次改動 改風格、改構圖、改規格後的重製 沒有上限,這層才會爆

前兩層是可以事先算的。第三層算不了,因為它取決於你改幾次主意。

而我這個專案的實際情形是:第三層已經發生過至少一次全員重製(中文檔名那批 20 張還留在 assets/turnarounds_old/,跟新的 20 張並存),而那次重製的觸發原因不是圖不好看,是檔名規範改了。

一個純粹的工程決定,觸發了一整輪生成成本。

已知的固定量

不能寫的是價格,能寫的是量。這些是實查得到的:

角色 prompt 檔(扣除 index.md)      20
會進入生成迴圈的                     20
一輪的 API 呼叫次數                  20

模型與端點也是確定的:走 OpenAI 的 /v1/images/edits,模型 gpt-image-1,每次呼叫都帶同一張固定的風格錨定圖 assets/char-tuner.png

所以一輪的成本結構是:

一輪成本 = 單張成本 × 20 × 重跑倍率

三個因子裡,我確定的是 20,不確定的是單張成本,而最危險的是重跑倍率

重跑倍率才是那個變數

單張成本是你選模型的時候就決定的,選了就固定,而且查得到。

重跑倍率不是。它等於「這批圖你重生了幾次」,取決於:

  • 規格有沒有一次講清楚(Day 15 講過的封面規格不同步,就是這種東西)
  • 冪等性有沒有壞(Day 16 那個 skip 失效,讓每次重跑都是滿額重跑)
  • 你會不會改主意

前兩項是工程問題,可以修。第三項是創作問題,修不了,只能框住。

我自己的實際倍率至少是 2(中文檔名一批、英文檔名一批)。如果那次我不小心直接重跑,就會變成 3。

所以個人創作者的預算控制,重點不是找更便宜的模型,是把倍率壓回 1。

便宜一半的模型省 50%。倍率從 3 壓到 1 省 67%,而且不用換模型、不用犧牲品質。

沒有單價的時候怎麼估

這是這篇真正可以帶走的部分。在你還沒花第一塊錢之前,就能算出上限:

一、數清楚「單位」有幾個          → 我的是 20 個角色
二、查那個模型的公開單價          → 官方定價頁,不用實跑
三、乘起來得到「一輪理論成本」    → 這是地板,不是天花板
四、乘上你誠實估計的重跑倍率      → 這才是你要準備的預算
五、把倍率寫進計畫,當成 KPI      → 目標是讓它趨近 1

第四步大部分人會跳過,然後預算就爆了。

我建議估倍率的時候用這個問法:這批東西,我有多少把握規格不會再改? 不確定的話倍率就從 2 起跳。

第五步是把它變成可管理的東西。倍率不是天災,它是「規格沒定好」和「腳本不冪等」的總和,兩個都是你能動的。

一個更省錢的量法

寫到這裡要補一件事:那行禁令其實留了一個出口。原文是「要測成本請先修 skip 邏輯,或單獨抽一個角色跑」。

單獨抽一個角色跑,就是 1 次呼叫,不是 20 次。這是合法的,也是取得單張成本最便宜的路。

我這次沒有跑,理由很簡單:我要的是「一輪全員重製的實際花費」,而抽一個角色只能給我單張價格,剩下的還是乘出來的。既然都是乘出來的,那我用官方定價頁乘也一樣,何必花這一塊錢。

這也是個判斷:測量本身要花錢的時候,先問你想知道的東西是不是非測不可。

如果我要的是「這個模型出圖品質行不行」,那非跑不可。要的是一個乘法的結果,查定價頁就夠了。

代價:一篇沒有數字的成本結算

這篇的代價很直接——它答應了一個數字,然後沒有給。

我可以有另外兩種寫法:

一種是估一個數字寫上去,加註「約」。讀起來完整多了,而且大概率沒人會查。但這個系列的規矩是量化陳述必須來自實測或實查,估算不算。一旦開了這個口,後面每個數字的可信度都要打折。

另一種是把這天跳過,等有數字了再寫。但那等於承認連載的節奏比誠實重要。

第三種就是這篇:講清楚為什麼沒有,以及沒有數字的情況下還能給出什麼。

代價是這篇讀起來不如「我花了 X 美金」那麼有衝擊力。我接受,因為一個編出來的數字對讀者的傷害,比一個誠實的空白大。你照著一個編的數字做預算,會賠錢;照著這篇的估算法做,至少方向是對的。

還有一個代價是:這件事到現在還沒修。禁令擋住了花錢,但它同時擋住了測量。一個沒修的 bug,會連帶擋掉你其他想做的事,這件事我是今天才體會到的。

帶走什麼

一、成本要拆成三層來看:一次性、每輪固定、每次改動。

前兩層算得出來,第三層算不出來。看到有人報「這個專案花了 X 元」,先問那是哪一層。多數人報的是第二層,而爆掉的都是第三層。

二、單價乘數量只是地板,真正的預算是再乘一次重跑倍率。

沒有把倍率放進去的估算,一定會低估。而倍率不是命運,它是規格穩定度和腳本冪等性的總和。

判斷句:這批東西的規格,我有多少把握不會再改? 沒把握就從 2 起跳。

三、省錢的順位是先降倍率,再談換模型。

換便宜模型是拿品質換錢,壓倍率是純賺。而且壓倍率的手段——把規格寫死、把 skip 邏輯修對、加 --dry-run——每一項都是你本來就該做的工程。

四、測量本身有成本的時候,先確認你非測不可。

問一句:這個數字我是要拿來做決定,還是拿來寫進報告?拿來做決定,就去測。只是想填一個欄位,查公開資料乘一乘就好。

五、「有空再修」不會發生,因為你回去的時候不會想起它。

我 08-07 打開了同一支腳本,修了旁邊的圍欄抽取邏輯,然後關掉。skip 那行就在上面幾行,我沒看見。

所以「等我下次動這個檔案就順手修掉」是假的。下次動這個檔案的時候,你腦子裡裝的是那時候要修的東西。

判斷句:這條待修事項,有沒有一個東西會在我下次執行時擋住我? 沒有的話,它就只是一個願望。這也是為什麼 --dry-run 比日誌裡的禁令強——一個會攔住你,一個要你記得。

六、答應過的東西沒做到,要說。

昨天說今天給數字,今天沒有;昨天說要修 skip,到現在沒修。這兩件事我都寫進來了。連載跟專案一樣,最貴的不是進度落後,是讀者以為你做完了。


明天 Day 18,講角色卡管線:為什麼出圖的提示詞裡,反而不准出現角色的名字。


上一篇
Day 16|「已存在就跳過」失效,20 個角色 100% 重生,而且不會報錯
系列文
《矽墟》:我把一部科幻小說當成軟體專案來管17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言