模組三|AI 生圖與生片產線(Day 10–19)
昨天講內容審核誤判。今天講一個更基礎、但每個人接圖像 API 都會遇到的問題:
你的圖在本機,服務在雲端。中間那一步怎麼走?
我要把兩張參考圖(角色三視圖 + 立繪)交給生成服務。它提供兩種方式:
| 方式 | 做法 |
|---|---|
media_upload |
跟服務要一組上傳憑證/簽名 URL,把 binary 傳上去,拿到一個 media id |
media_import_url |
你給一個公開可存取的圖片 URL,服務自己去抓 |
第一直覺是選 media_upload。它「比較正式」:檔案直接從我這裡到它那裡,不經過第三方,看起來比較乾淨。
我最後選了 media_import_url:把圖丟到自己的靜態站部署上當圖床,然後給 URL。
理由有兩個,第二個才是重點。
media_upload 的典型流程是三段:
三個步驟、三個可能失敗的地方,而且簽名通常有時效。中間任何一步出錯,你要判斷是憑證過期、還是傳輸中斷、還是 id 沒對上。
media_import_url 只有一步:把 URL 字串放進請求裡。
我本來就有一個靜態站部署(那是專案的角色頁),圖放進去 push 一下就有公開網址。這個基礎設施已經存在,所以邊際成本是零。

這才是真正的差別。
用 URL 的話,我可以在送出生成請求之前做這件事:
# 本地檔案的 hash
shasum -a 256 assets/turnarounds/char-chenger-turnaround.png
# 服務將會抓到的東西的 hash
curl -sL "https://<我的靜態站>/char-chenger-turnaround.png" | shasum -a 256
兩個 hash 一樣,我就知道:服務去抓的時候,拿到的跟我本機這張是同一個 byte 序列。
不一樣的話,我立刻知道問題在傳輸/部署/快取,而不是在生成階段。
用 media_upload 就很難做這件事。圖傳上去之後變成一個 media id,你沒有辦法簡單地把它抓回來比對,它進了一個你看不到的地方。
因為圖像生成是一個回饋很慢、很貴、而且結果本來就有隨機性的操作。
假設生成結果不對。可能的原因有:
這三種的處理方式完全不同,而第 1 種是最蠢、最容易發生、也最容易被忽略的。
hash 比對可以在花錢之前把第 1 種完全排除掉。剩下的排查範圍就小很多。
昨天 Day 13 那個 NSFW 誤判,我繞了四次遠路的原因就是輸入清單沒被逐項確認。能夠事前驗證的輸入,就該事前驗證掉。

回頭看,這個選擇的形狀在別的地方一直出現:
| 封閉通道 | 開放通道 | |
|---|---|---|
| 例子 | 簽名上傳、私有 bucket、二進位協定 | 公開 URL、明文設定檔、REST + JSON |
| 好處 | 安全邊界清楚、不需要對外曝露 | 中間狀態可以被檢查 |
| 壞處 | 出事時你看不到中間發生什麼 | 東西是公開的 |
可觀測性和封閉性是互相衝突的。
我選開放通道,是因為在這個場景裡我最痛的是排查成本,而不是保密。但這個判斷會隨場景反轉,下面就講它的代價。
代價一:那些圖是公開的。
這是最實在的代價,必須講清楚。
media_import_url 要求 URL 公開可存取,服務端要能匿名抓到它。也就是說,任何拿到網址的人都看得到那張圖。
對我來說這可以接受,因為那些角色圖本來就會出現在公開的角色頁上。但如果是還沒公開的設計、客戶的素材、或任何有保密需求的東西,這條路直接出局。
判準很簡單:這張圖如果現在被陌生人看到,會不會有問題? 會的話,走簽名上傳,接受排查困難。
代價二:多了一個依賴。
生成請求現在依賴我的靜態站活著。部署掛了、網址改了、檔案被清掉,生成就會失敗,而且錯誤訊息會是生成服務那邊回報的「抓不到圖」,不是我這邊。
我把一個單向的操作,變成了一個需要兩個系統同時正常的操作。
代價三:快取。
我踩過一次:換了圖但沿用同一個檔名,CDN 還在服務舊的那張,於是生成結果一直是舊角色。
hash 比對正好抓得到這件事,這也是我後來養成先比對的習慣的原因。但如果沒比對,這種錯誤會偽裝成「模型不聽話」。
一、接外部服務時,優先選「中間狀態可以被檢查」的通道。
尤其是當這個操作很貴、很慢、或結果有隨機性的時候。
因為在這種操作裡,「輸入到底對不對」的排查成本特別高,你不能靠重跑幾次來確認。
判斷句:如果結果不如預期,我能不能證明輸入是對的?
證明不了的話,你每次排查都要把「輸入可能沒傳對」放在可能性清單裡,而它會污染你所有的推論。
二、能事前驗證的,不要留到事後排查。
hash 比對只要一行 curl | shasum,但它把一整類問題永久排除了。
一般化:任何「送出去之前可以確認」的東西,都值得花那三十秒。 送出去之後才發現,你要付的是整趟往返的成本。
三、可觀測性 vs 封閉性是真的要選一個。
不要以為有兩全其美的方案。封閉的通道就是看不到裡面,開放的通道就是東西會曝露。
選的方法是問:在這個專案裡,我比較常付哪一種代價?
我這個專案是前者,所以選了看起來比較笨的那條。換一個保密要求高的專案,我會選相反的。
明天 Day 15,講換模型之後留下的爛攤子:不同模型的輸出解析度不一樣,怎麼統一。 我的鏈是「先超過再縮回去」:1k 出圖 → 放大到 2k(實出遠超過)→ 本地縮到統一規格。以及一個維護技巧:檔名沿用舊名,讓下游的 HTML 一行都不用改。