廣告位招商中 歡迎洽談

將 Dezgo REST API 整合至 Web 應用程式:按量計費文字生成圖片與局部重繪開發指南

365Finds Editorial
已收錄 11,430 篇 Wiki 文章

讓你的 AI 用上 365 Wiki

複製下方的提示詞,貼給你常用的 AI,然後直接提問。

下載完整版 Skill

先用提示詞體驗;經常使用時,安裝完整版 365Wiki Skill,以後無需重複複製。沒有常用 AI?Gemini、Microsoft Copilot 等網頁版也可以。

365Wiki Skill

在自研 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)格式,伺服端能直接讀取回傳的二進位檔案資料。

重要請求參數

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,支援更高細節與原生高解析度輸出)。

遮罩規範與影像格式

呼叫局部重繪時必須成對提供兩張圖片:

  1. init_image:原始待編輯的基底圖片(PNG 或 JPEG 二進位資料)。
  2. 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 回應標頭皆包含完整的財務統計資訊:

零消耗餘額查詢端點

若想定期確認帳戶財務狀態而不觸發圖片生成,可直接發送請求至流水帳端點:

curl -s -H "X-Dezgo-Key: YOUR_API_KEY" https://api.dezgo.com/account/tx/last

此端點將回傳包含最新交易紀錄與目前 balance 數值的 JSON 物件,非常適合搭配 Cron 任務定時排程檢查。

常見 HTTP 異常處理策略

  1. HTTP 402 (Payment Required):預付餘額耗盡。後端攔截到此錯誤時,應觸發高優先順序警報至團隊通訊頻道,並向終端用戶呈現友善的降級提示(例如「影像處理排隊中,請稍後查看」),防止伺服器拋出 500 內部錯誤。
  2. HTTP 429 (Too Many Requests):超出並發限制。應在 Worker 內建指數退避重試邏輯(如 1 秒、2 秒、4 秒後重試)。
  3. HTTP 400 (Bad Request):多為遮罩圖片與底圖尺寸不合,或輸入了不支援的模型參數。發送至 Dezgo 前務必在後端先檢驗圖片幾何規格。

結論

對於追求高成本效益的獨立開發者與精實 SaaS 團隊而言,Dezgo 提供了一條跳過 GPU 繁重維運並擺脫昂貴月費綁定的捷徑。透過在自建後端封裝 API 代理、結合 Redis 佇列處理長耗時繪圖,並持續監控回應標頭落實即時財務防護,即可打造出彈性高、成本低至分厘且高可靠的商業級生成式 AI 應用。

參考資料