把影像整合遷移到 SeedRouter
把 GPT Image 2 整合遷移到 SeedRouter:對應請求欄位、處理非同步任務,並驗證以 URL 為基礎的影像交付。
以 Markdown 閱讀把影像 API 遷移到 SeedRouter,需要核對請求與回應的合約,而不只是換掉 API 金鑰和基礎 URL。GPT Image 2 使用的是大家熟悉的那套影像生成欄位,但提交之後回傳的是一個任務 ID。你的應用程式必須儲存這個 ID、輪詢直到完成,然後讀取生成好的影像 URL。
最小可用的遷移,是從伺服器端程式碼發起一次文字轉影像請求。先把這一條跑通,再去遷移參考影像編輯、遮罩或更大的批次。在新路徑通過同樣的驗收檢查之前,請保留現有整合可用。
哪些假設需要改變?
找到那段把影像請求變成可用檔案的程式碼。它現在可能期望首個回應裡就帶著影像、可能在解碼一個 base64 欄位,或者在用 multipart 上傳。這些假設都必須逐條對照 SeedRouter 的 GPT Image 2 參考文件核實。
| 現有假設 | SeedRouter 的合約 | 應用程式需要的改動 |
|---|---|---|
| 提交後回傳成品影像 | 提交後回傳一個任務參考 | 在等待輸出之前先儲存 id |
輸出在提交回應的 data 陣列裡 | 已完成任務的影像在 output.data 中 | 在任務完成後再讀取結果 |
用戶端解碼 b64_json | 影像以託管 URL 的形式回傳 | 下載回傳的這些 URL |
| 編輯時上傳檔案位元組 | 參考影像使用 images 的 URL 物件 | 讓輸入影像可以透過 URL 存取 |
| 用一個獨立的編輯路徑來選擇編輯 | 由 images 和 mask 決定執行哪種操作 | 統一使用對外的 generations 端點 |
| 用戶端逾時代表出圖失敗 | 任務可能仍在處理中 | 用儲存下來的 ID 繼續查詢 |
這就是為什麼即便某個同步的 Images SDK 支援設定基礎 URL,它也不是可以直接替換的方案。該保留的模型設定照舊保留,但要改造那段等待並消費結果的應用程式碼。
先對應請求欄位,再動程式碼
先從 model、prompt、size、quality 和 n 開始。模型 ID 使用 gpt-image-2。尺寸請明確寫成 1024x1024 這樣的值,或者使用 auto;不要把原有的 resolution 欄位或一個比例字串直接當作尺寸沿用過來。
SeedRouter 的 OpenAPI 文件是核對時很好的對照材料。請比對你的應用程式實際送出的欄位,包括 SDK 自動補上的值,而不是只看呼叫處能看到的那幾個參數。未知欄位會被拒絕。
對這個模型來說,style、response_format 以及可設定的 input_fidelity 都不是被接受的請求欄位。請把這些假設刪掉,而不是塞進一個通用的 options 物件裡藏起來。請求同樣不支援 stream 和 partial_images;在這套整合裡,進度是透過任務狀態來回報的。
輸出設定之間存在相依關係。需要透明效果時,請選擇 PNG。output_compression 只在 JPEG 下傳入,PNG 不要傳。壓縮值為 0 是合法的,所以不要用真值判斷把它換成預設值。這些細節很小,一次成功的基本請求根本覆蓋不到。
換掉「回應是同步的」這個假設
下面這段 Node.js 範例提交一次請求並印出任務 ID。請在伺服器上設定 SEEDROUTER_API_KEY;絕不要把金鑰放進瀏覽器程式碼或公開的環境變數裡。
const response = await fetch('https://api.seedrouter.ai/v1/images/generations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SEEDROUTER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-image-2',
prompt: 'A cobalt-blue ceramic mug on a pale gray tabletop.',
size: '1024x1024',
quality: 'low',
n: 1,
}),
signal: AbortSignal.timeout(60000),
});
const task = await response.json();
if (!response.ok) {
// Preserve a task reference if one accompanies an uncertain submission.
if (typeof task.id === 'string') console.log('Task reference:', task.id);
throw new Error(`Submission needs review: HTTP ${response.status}`);
}
if (typeof task.id !== 'string' || !task.id) throw new Error('Missing task ID.');
console.log(task.id); // Persist this ID with your application's image record.手動冒煙測試時,印出 ID 就夠了。但在真實應用程式裡,請在把控制權交還給使用者之前先把它存下來。這樣即使使用者已經跳轉到別處,你的影像記錄也能保持在「處理中」狀態,之後再查詢就能把結果取回來。
用同樣的授權標頭呼叫 GET https://api.seedrouter.ai/v1/tasks/{id} 來查詢進度。狀態為 completed 時讀取 output.data[].url;狀態為 failed 時,依文件處理對應錯誤並顯示合適的失敗狀態。想要一個能持久化進度的可執行範例,請看批次提交與輪詢。
不要把 API 金鑰附加到影像下載請求上。授權屬於任務 API 呼叫,而不屬於單獨去抓取那個回傳的資源 URL。
把參考影像和遮罩改為 URL 輸入
原本以本機檔案為基礎的流程,需要多一個準備步驟:把參考影像放到一個你可控、可存取的 HTTP(S) URL 上。然後以 images: [{"image_url": "https://example.com/reference.png"}] 的形式傳入,並把這個位址換成你自己的。不要傳檔案路徑、blob: URL、base64 的 data URL 或 Files ID。
請確認這個 URL 在沒有瀏覽器登入 cookie 的情況下也能開啟。只有在你已登入的工作階段中才能存取的 URL,對這個請求來說不是可用的參考影像。任務處理期間請保持圖片可存取,不要一提交就撤銷存取權限。
遮罩使用 mask: {"image_url": "https://example.com/mask.png"} 的形式,並且必須與參考影像一起使用,尺寸要與第一張參考影像一致。在遷移既有的編輯流程之前,請先讀完全部媒體輸入限制,尤其是檔案格式和檔案大小。
遷移的驗收測試該涵蓋什麼?
請測試你的應用程式真正依賴的行為,包括被中斷的情況。一張成功的圖只能證明那一次請求成功了,它並不能證明你的「處理中」狀態能撐過一次重新整理,也不能證明下載失敗時不會重複生成。
- 提交一次純文字請求,並在輪詢之前先把回傳的 ID 存下來。
- 停止輪詢,再用同一個 ID 重新開始,確認沒有產生額外的 POST 請求。
- 把
processing、completed和failed當作三種彼此不同的狀態來處理。 - 在不傳送 API 授權標頭的情況下,下載一張已完成的影像。
- 用一個可存取的 URL 驗證參考影像編輯,再用一個無法存取的 URL 驗證失敗處理。
- 用公開的 schema 驗證選用欄位,其中包括壓縮值設為 0 的情況。
- 確認帳號扣款是從用量記錄裡讀取的,而不是從一個憑空臆造的任務回應費用欄位裡讀取的。
可重複的失敗與逾時測試,請使用模擬回應。只有在這些檢查都通過之後,再有意識地做一次小規模的真實測試;真實生成是要消耗餘額的。如果提交結果不確定,請先排查再重試。本機拋出的例外,並不能證明沒有任務被受理。
常見問題
現有的提示詞還能繼續用嗎?
可以,作為起點使用,前提是它們滿足請求的各項限制。請保留幾條有代表性的提示詞用於對比,但不要指望重複生成會得到完全相同的影像。
我需要換一個用戶端函式庫嗎?
就本文的範例而言不需要,標準的 HTTP 請求就夠了。無論你選擇哪個用戶端,它都必須能處理任務提交與輪詢,而不是期望立刻拿到一張成品圖。
最終費用在哪裡查看?
在帳號用量記錄中查看。已完成的任務可能會帶上 token 用量,但它對外的回應中沒有金額欄位。估算方法見價格指南。
在應用程式邊界上完成這次遷移
當應用程式能完整處理結果的整個生命週期——任務受理、處理中狀態、最終輸出、下載以及失敗——這次影像 API 遷移才算完成。第一步改動要小,把被中斷的情境測到位,等輸入和輸出的假設都核實過之後,再遷移剩下的請求。



