在自研 Web 應用程式中引入 AI 影像生成與局部重繪功能時,獨立全端開發者與精簡工程團隊常面臨兩難的架構取捨。一方面,在雲端自行建置與託管開源擴散模型(例如租用 AWS EC2 G5 執行個體、RunPod 容器或專用 GPU 節點),必須背負沉重的 CUDA 驅動程式維護、vLLM/Diffusers 版本相容性問題、冷啟動延遲以及每月 150 至 400 美元以上的閒置算力低消;另一方面,主流商業 SaaS 平台(如 Midjourney、Leonardo 或 Adobe Firefly)則多半採取每人每月數十美元的強制訂閱制度,點數逾期作廢,且缺乏專為自動化打造的透明 API 方案。
Dezgo 憑藉其極簡 REST API 與真正的按用量計費(Pay-as-you-go)機制,有效化解了此架構痛點。開發者僅需向預付錢包存入底金(最低儲值僅需 10 美元,點數永久有效),標準 512x512 Stable Diffusion 渲染成本低至約 0.0019 美元,並依據解析度與取樣步數透明遞增。
本指南專為全端與後端工程師撰寫,深入剖析 Dezgo 官方 REST API 的接入規格與 X-Dezgo-Key 鑑權機制,示範如何在伺服端呼叫 /text2image 與 /inpainting_sdxl 端點、透過 HTTP 回應標頭監控即時餘額,並利用任務佇列與回呼機制處理非同步渲染。
架構選型比較:自建 GPU 叢集、商用 SaaS 與 Dezgo
在撰寫程式碼前,先從成本結構、維運負擔與工程彈性評估三種方案:
| 評估維度 | 自建 GPU 節點 (AWS / RunPod) | 主流商用 SaaS (Midjourney 等) | Dezgo REST API |
|---|---|---|---|
| 最低成本門檻 | 高;每月至少 150–500 美元閒置算力固定支出 | 偏高;每位使用者每月 10–60 美元固定月租 | 極低;10 美元一次性預付儲值;零月租低消 |
| 單張圖片成本 | 浮動劇烈;離峰時段單張折算成本居高不下 | 固定額度包;當月未使用點數自動過期 | 約 $0.0019/張 (512px SD);步數與像素精確折算 |
| 維運複雜度 | 極高;需管理顯示卡驅動、記憶體洩漏與自動擴展 | 極低;全黑盒託管;但無法靈活客製 | 極低;標準 HTTP REST 介面;零 GPU 維運負荷 |
| 模型支援度 | 極高;可自由載入任何 HuggingFace 權重與微調 LoRA | 極低;僅能使用廠商封閉黑盒模型 | 良好;原生支援 SD 1.5、SD 2.1、SDXL、Lightning 與 LoRA |
| 資料回應契約 | 需自行開發 API 與序列化資料傳輸架構 | 多仰賴 Discord 機器人或非標準輪詢機制 | 同步直出二進位影像串流 (image/png);標頭傳回費用 |
Dezgo 的核心價值在於將擴散模型的推論開銷簡化為標準 HTTP 呼叫,且每次呼叫的實際扣款與即時可用餘額均可於回應標頭取得。
鑑權機制與安全性架構設計
Dezgo 官方 API 採用金鑰鑑權機制,所有發送至 api.dezgo.com 的請求皆必須在標頭中攜帶 X-Dezgo-Key。開發者可於 dezgo.com/account 儀表板中產生金鑰。
核心安全準則:嚴禁於前端瀏覽器直連 Dezgo
由於 Dezgo 金鑰直接扣抵開發者帳戶的真實預付美金,且平台並未提供針對終端使用者的權限沙盒,若將 X-Dezgo-Key 洩漏於前端網路傳輸、用戶端打包程式碼或瀏覽器儲存區中,惡意使用者只需擷取該金鑰即可在短時間內耗盡你的所有儲值餘額。
因此,安全可靠的 Web 系統架構必須始終將 Dezgo 呼叫收斂於受信任的後端伺服器或 API 代理層:
[前端瀏覽器 Client]
│
│ 1. POST /api/generate (攜帶使用者登入 Session / Token)
▼
[自建後端伺服器]
│
│ 2. 驗證權限、扣減系統內部額度、檢查 Prompt
│ 3. 注入私密請求標頭 "X-Dezgo-Key"
│ 4. POST https://api.dezgo.com/text2image
▼
[Dezgo REST 運算叢集]
│
│ 5. 同步回傳 PNG 二進位串流與扣款標頭
▼
[自建後端伺服器]
│
│ 6. 解析 x-dezgo-job-amount-usd 與 x-dezgo-balance-total-usd
│ 7. 上傳至物件儲存 (S3 / R2) 或直串轉發前端
▼
[前端瀏覽器 Client]
步驟一:整合文字生成圖片端點 (/text2image)
Dezgo 的文字生成圖片端點支援 multipart/form-data 與 application/json(搭配 base64)格式,伺服端能直接讀取回傳的二進位檔案資料。
重要請求參數
prompt(字串,必填):描繪所需影像內容的正向提示詞。negative_prompt(字串,選填):負向提示詞,用於排除畸形肢體、模糊雜訊等不良生成結果。model(字串,選填):所選用的 AI 模型識別碼。可透過GET https://api.dezgo.com/info動態取得可用清單(例如stablediffusion_1_5、stablediffusion_2_1_768px等)。guidance(浮點數,選填):分類器自由引導比例(CFG Scale),通常設定於 6.0 至 9.0 之間(預設約 7.5)。steps(整數,選填):去噪取樣步數(一般為 20–50)。步數越高細節越豐富,但運算時間與扣款費用將等比增加。sampler(字串,選填):取樣演算法(如euler_a、ddim、dpmpp_2m)。width/height(整數,選填):影像寬度與高度像素(預設 512x512)。
Node.js / TypeScript 後端實作範例
以下是適用於 Express 或 Next.js API Routes 的後端實作:
// server/services/dezgoService.ts
import { Buffer } from "node:buffer";
interface TextToImageParams {
prompt: string;
negativePrompt?: string;
model?: string;
guidance?: number;
steps?: number;
width?: number;
height?: number;
}
interface GenerationResponse {
imageBuffer: Buffer;
contentType: string;
jobCostUsd: number;
remainingBalanceUsd: number;
}
export async function generateTextToImage(
params: TextToImageParams
): Promise<GenerationResponse> {
const apiKey = process.env.DEZGO_API_KEY;
if (!apiKey) {
throw new Error("環境變數 DEZGO_API_KEY 未設定,無法發起請求。");
}
const formData = new FormData();
formData.append("prompt", params.prompt);
if (params.negativePrompt) {
formData.append("negative_prompt", params.negativePrompt);
}
if (params.model) {
formData.append("model", params.model);
}
if (params.guidance) {
formData.append("guidance", params.guidance.toString());
}
if (params.steps) {
formData.append("steps", params.steps.toString());
}
if (params.width) {
formData.append("width", params.width.toString());
}
if (params.height) {
formData.append("height", params.height.toString());
}
const response = await fetch("https://api.dezgo.com/text2image", {
method: "POST",
headers: {
"X-Dezgo-Key": apiKey,
},
body: formData,
});
if (!response.ok) {
const errorBody = await response.text();
handleDezgoHttpError(response.status, errorBody);
}
// 從 HTTP 回應標頭中擷取單次作業費用與帳戶可用餘額
const jobCostUsd = parseFloat(
response.headers.get("x-dezgo-job-amount-usd") || "0"
);
const remainingBalanceUsd = parseFloat(
response.headers.get("x-dezgo-balance-total-usd") || "0"
);
const arrayBuffer = await response.arrayBuffer();
const imageBuffer = Buffer.from(arrayBuffer);
const contentType = response.headers.get("content-type") || "image/png";
return {
imageBuffer,
contentType,
jobCostUsd,
remainingBalanceUsd,
};
}
function handleDezgoHttpError(status: number, message: string): never {
switch (status) {
case 400:
throw new Error(`Dezgo 請求參數錯誤 (400): ${message}`);
case 401:
throw new Error("Dezgo 鑑權失敗 (401): 請檢查 X-Dezgo-Key 是否正確。");
case 402:
throw new Error("Dezgo 餘額不足 (402): 預付帳戶已耗盡,請前往儲值。");
case 429:
throw new Error("Dezgo 請求頻率過高 (429): 超過速率限制,需指數退避重試。");
default:
throw new Error(`Dezgo API 例外錯誤 (${status}): ${message}`);
}
}
步驟二:整合 SDXL 局部重繪端點 (/inpainting_sdxl)
局部重繪(Inpainting)讓使用者能夠在維持原有圖像背景與構圖的前提下,只針對遮罩選取範圍進行語意重繪與物件替換。Dezgo 提供了兩個主要端點:/inpainting(標準 SD 模型)與 /inpainting_sdxl(基於 Stable Diffusion XL,支援更高細節與原生高解析度輸出)。
遮罩規範與影像格式
呼叫局部重繪時必須成對提供兩張圖片:
init_image:原始待編輯的基底圖片(PNG 或 JPEG 二進位資料)。mask_image:黑白遮罩圖,其像素尺寸必須與init_image完全一致。白色像素(#FFFFFF)代表需要重繪的範圍;黑色像素(#000000)代表嚴格保留的原圖像素。
Python 後端實作範例 (FastAPI / Requests)
# app/services/dezgo_inpainting.py
import os
import requests
from typing import Dict, Any, Tuple
DEZGO_API_KEY = os.environ.get("DEZGO_API_KEY")
INPAINTING_SDXL_URL = "https://api.dezgo.com/inpainting_sdxl"
def execute_sdxl_inpainting(
prompt: str,
init_image_bytes: bytes,
mask_image_bytes: bytes,
negative_prompt: str = "",
guidance: float = 7.5,
steps: int = 30,
) -> Tuple[bytes, Dict[str, Any]]:
"""
使用 multipart/form-data 向 Dezgo SDXL 端點送出局部重繪任務
"""
if not DEZGO_API_KEY:
raise ValueError("系統環境變數中未設定 DEZGO_API_KEY。")
headers = {
"X-Dezgo-Key": DEZGO_API_KEY
}
files = {
"init_image": ("init.png", init_image_bytes, "image/png"),
"mask_image": ("mask.png", mask_image_bytes, "image/png"),
}
data = {
"prompt": prompt,
"negative_prompt": negative_prompt,
"guidance": str(guidance),
"steps": str(steps),
}
response = requests.post(
INPAINTING_SDXL_URL,
headers=headers,
files=files,
data=data,
timeout=60
)
if response.status_code == 402:
raise RuntimeError("Dezgo 預付餘額已用盡,請至控制台儲值。")
elif response.status_code != 200:
raise RuntimeError(f"Dezgo 局部重繪失敗 [HTTP {response.status_code}]: {response.text}")
metadata = {
"job_cost_usd": float(response.headers.get("x-dezgo-job-amount-usd", "0")),
"remaining_balance_usd": float(response.headers.get("x-dezgo-balance-total-usd", "0")),
"content_type": response.headers.get("Content-Type", "image/png"),
}
return response.content, metadata
步驟三:Web 應用程式中的非同步工作流程與逾時防護
Dezgo 的 REST API 採用同步阻塞式設計,意即發出請求後,伺服端連線會保持開啟直到模型運算完成(通常耗時約 2 至 8 秒,取決於模型大小與步數)。
Serverless 與短連線環境的逾時風險
若在無伺服器架構(例如 Vercel 預設的 10 秒上限)或短連線反向代理中直接同步等待 Dezgo 回傳,極易因網路波動或佇列等待而引發 Gateway Timeout。因此,在生產環境中建議採用「後台任務佇列 + 狀態輪詢/事件推播」的解耦架構:
[Web 前端 Client] ── 1. POST /api/jobs (送出提示詞與遮罩) ──► [Web 伺服器 API]
│
▼
[Web 前端 Client] ◄─ 3. 回傳 202 Accepted { jobId } ── 2. 推送至 Redis 佇列
│ │
│ ▼
│ 4. 監聽 SSE / WebSocket 或定期輪詢狀態 [Redis / BullMQ]
│ │
│ ▼ 5. 提取任務
│ [背景 Worker 程序]
│ │
│ ├── 6. 呼叫 Dezgo API
│ ├── 7. 轉存至物件儲存區
│ └── 8. 寫入完成狀態
◄── 9. 推送渲染完成事件與 CDN 圖片網址 ─────────────────┘
BullMQ 背景 Worker 實作範例
// workers/renderWorker.ts
import { Worker, Job } from "bullmq";
import { generateTextToImage } from "../services/dezgoService";
import { uploadToObjectStorage } from "../services/storageService";
import { database } from "../services/db";
export const renderWorker = new Worker("image-generation-queue", async (job: Job) => {
const { prompt, userId, jobId } = job.data;
// 1. 呼叫 Dezgo 伺服端服務模組
const { imageBuffer, contentType, jobCostUsd, remainingBalanceUsd } =
await generateTextToImage({ prompt, steps: 30 });
// 2. 將產生的二進位圖片存入雲端物件儲存 (S3 / R2)
const cdnUrl = await uploadToObjectStorage({
path: `outputs/${userId}/${jobId}.png`,
data: imageBuffer,
contentType,
});
// 3. 更新資料庫作業狀態與財務扣款紀錄
await database.job.update({
where: { id: jobId },
data: {
status: "SUCCESS",
resultUrl: cdnUrl,
actualCostUsd: jobCostUsd,
},
});
// 4. 餘額預警機制:可用金額過低時發送通報
if (remainingBalanceUsd < 5.0) {
console.warn(`[財務預警] Dezgo API 預付餘額過低: 目前僅存 $${remainingBalanceUsd.toFixed(2)}`);
}
return { cdnUrl, jobCostUsd };
});
財務餘額管理與生產維運防護守則
由於 Dezgo 目前不提供信用卡自動透支扣款功能,開發者必須在餘額歸零前手動儲值。將餘額監控整合至日常維運流程是維持系統不中斷運作的關鍵。
回應標頭遙測指標
每次生成成功時,Dezgo 回應標頭皆包含完整的財務統計資訊:
x-dezgo-job-amount-usd:該次作業扣除的精確美金金額。x-dezgo-balance-total-usd:扣除該次費用後,帳戶即時可用總餘額(美元)。x-dezgo-balance-credits-usd:歷史儲值總額。x-dezgo-balance-debits-usd:歷史消耗總額。x-dezgo-balance-index:帳本交易序號。
零消耗餘額查詢端點
若想定期確認帳戶財務狀態而不觸發圖片生成,可直接發送請求至流水帳端點:
curl -s -H "X-Dezgo-Key: YOUR_API_KEY" https://api.dezgo.com/account/tx/last
此端點將回傳包含最新交易紀錄與目前 balance 數值的 JSON 物件,非常適合搭配 Cron 任務定時排程檢查。
常見 HTTP 異常處理策略
- HTTP 402 (Payment Required):預付餘額耗盡。後端攔截到此錯誤時,應觸發高優先順序警報至團隊通訊頻道,並向終端用戶呈現友善的降級提示(例如「影像處理排隊中,請稍後查看」),防止伺服器拋出 500 內部錯誤。
- HTTP 429 (Too Many Requests):超出並發限制。應在 Worker 內建指數退避重試邏輯(如 1 秒、2 秒、4 秒後重試)。
- HTTP 400 (Bad Request):多為遮罩圖片與底圖尺寸不合,或輸入了不支援的模型參數。發送至 Dezgo 前務必在後端先檢驗圖片幾何規格。
結論
對於追求高成本效益的獨立開發者與精實 SaaS 團隊而言,Dezgo 提供了一條跳過 GPU 繁重維運並擺脫昂貴月費綁定的捷徑。透過在自建後端封裝 API 代理、結合 Redis 佇列處理長耗時繪圖,並持續監控回應標頭落實即時財務防護,即可打造出彈性高、成本低至分厘且高可靠的商業級生成式 AI 應用。