← 部落格

Z-Image-Base API 完整指南:CFG + 負面提示詞實戰應用

Z-Image-Base API 完整教學:CFG 參數調整、negative_prompt 使用方法、參考圖像引導、強度控制。包含 Python/cURL 程式碼範例。

4 min read
Z-Image-Base API 完整指南:CFG + 負面提示詞實戰應用

嗨,我是 Dora。一個小小的不便竟然讓我深入研究了 Z-Image-Base API。我手邊有一批參考圖片、需要保持一致風格的文案,卻沒有足夠時間一一調整提示詞。我不斷看到有人手動微調設定,然後貼出一次性的成果。這樣做示範沒問題,但我的工作需要每週能穩定執行兩次、不會出現意外的方案。於是,在 2026 年 1 月至 2 月的幾個工作階段裡,我接入了 Z-Image-Base,仔細觀察它在哪些地方會抵抗我,並記錄下真正讓它變得可靠的做法。

這篇文章不是每個參數的全面介紹,而是我反覆調整的部分,以及那些能減少心智負擔的小調整。如果你被各種 AI 工具包圍,只想找一個行為可預期的,這或許能幫上忙。

API 基本設定

取得 WaveSpeed API 金鑰

我註冊後從 WaveSpeed 控制台取得了一組 API 金鑰。沒什麼特別之處。有一點小提示:金鑰權限是依專案範圍設定的。在協作工作流程中很方便,但這意味著你最好一開始就把專案名稱取清楚。我專門為圖片實驗建立了一個專案,這樣日誌和配額就不會與正式環境混在一起。

如果你會定期輪換金鑰(我每個月都會),Z-Image-Base 的處理非常乾淨俐落。我在環境變數中替換了金鑰,重新執行腳本,完全沒有殘留的驗證狀態。這本來就應該如此,但第一次嘗試就成功,我還是鬆了一口氣。

Endpoint URL 結構

基本架構看起來是標準的 REST 設計,加上模型切換功能:

  • 基礎位址:https://api.wavespeed.ai
  • 版本化路徑:/v1/images
  • 模型選擇器:model: "Z-Image-Base"

實際使用中,純提示詞的請求我傳送 POST 至 /v1/images/generations,傳入參考圖片時則使用 /v1/images/edits。比起塞滿參數的查詢字串,我更喜歡清晰的路徑,這個設計符合我的思考方式。如果你的路由方式不同,模型名稱依然重要:Z-Image-Base 看起來比一些更花俏的模型保守一些,這點我很喜歡。

驗證標頭設定

這裡沒什麼複雜的,但拼寫必須完全正確:

  • Authorization: Bearer YOUR_WAVESPEED_API_KEY
  • Content-Type: application/json(純提示詞時使用)
  • Content-Type: multipart/form-data(上傳圖片時使用)

我把金鑰存在 .env 檔案中,執行時再載入。這很無聊,但能防止意外提交。另外:如果你從 CI 執行腳本,請將金鑰設定為遮罩的 secret,並避免記錄完整的請求內容。這很顯而易見,但值得一提。一行多餘的日誌可能讓你後悔很久。根據 WaveSpeed 的安全最佳實踐,API 金鑰應儲存在環境變數中,絕不暴露在前端程式碼裡,並定期輪換。

核心參數詳細說明

prompt — 正向提示詞的撰寫方式

我沒有過度思考提示詞的風格。使用 Z-Image-Base 時,簡單的正向提示詞比華麗的敘述更有效。我的寫法是先寫意圖,再寫限制條件:

  • 「編輯風格的產品照,亞麻桌上的陶瓷馬克杯,柔和的清晨光線。」
  • 然後加上細節:「35mm 風格,中性色調分級,無文字,背景簡潔。」

除非需要表現動態,否則我不使用動詞。當我保持具體描述時,模型的表現非常穩定:材質、光線、鏡頭感、背景類型。一旦我加入感覺性描述,它就會飄移。如果我寫「舒適的極簡風」,我會得到蠟燭混亂的畫面。當我改寫成「柔和光線,單一散射光源,無蠟燭」,它就乖乖配合了。

negative_prompt — 排除不想要的元素

一開始我抗拒使用負向提示詞,但它後來成了我的安全護欄。我保留了一組簡短的基本設定,反覆重複使用:

  • 「no text, no watermark, no extra hands, no extra limbs, no logo, no signature, no border」

加上這些後,後期清理的時間大幅縮短。它無法解決每一個邊緣案例(馬克杯上有時還是會出現戒指),但已足夠降低奇怪結果的比例,讓我不需要為小批次任務重新生成。需要嚴格的產品視角時,我加上「no dramatic perspective, no tilt」,就能得到更水平的構圖。

guidance_scale(CFG)— 控制提示詞的遵循程度

這個參數比我預期的更重要。我的筆記如下:

  • 5–6:較寬鬆,多一點紋理感和即興發揮
  • 7–8:可靠穩定,大多數任務我都用這個範圍
  • 9 以上:字面遵循,但光線有時會變得脆弱,色彩也較為平淡

有好的參考圖片時,我會把 CFG 降到 6–7,能得到更好的微對比效果。沒有參考圖片時,7.5 是我的中位值。根據 Z-Image 技術文件,該模型支援完整的 Classifier-Free Guidance(CFG),為複雜的提示詞工程提供精準控制。超過 9 的感覺就像叫一個已經很謹慎的朋友再更謹慎一點——沒有錯,只是稍微少了點生命力。

image + strength — 參考圖片引導

這對組合承擔了最繁重的工作。我附上一張參考 JPG,透過調整 strength 來控制模型的跟隨程度:

  • 0.25–0.35:輕觸,保留調色板和氛圍
  • 0.45–0.6:穩固貼合,構圖保持接近
  • 0.7 以上:接近複製,適合在小幅風格變化下生成變體

我沒料到 0.5 會是最佳點,但確實如此。足夠的結構能保持版面配置,又有足夠的自由度讓光線調整得以發揮。強度太高會讓它變得固執:如果原圖在錯誤位置有陰影,模型就會緊抓不放。後來我改為在提示詞中加上「shadow on camera-left」,並降低 strength,重試次數因此減少了。

一個實用提示:上傳前我會將參考圖片的長邊調整為 1024。統一的尺寸讓裁切和速度更加可預測,在大量迭代中也能節省一些頻寬。

程式碼實作

cURL 快速測試

接入新的 endpoint 時,我習慣先用 cURL 查看回應的結構和錯誤代碼。

curl -X POST \
  https://api.wavespeed.ai/v1/images/generations \
  -H "Authorization: Bearer $WAVESPEED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Z-Image-Base",
    "prompt": "Editorial-style product photo of a ceramic mug on a linen table, soft morning light. 35mm look, neutral color grading, no text, uncluttered background.",
    "negative_prompt": "no text, no watermark, no extra hands, no extra limbs, no logo, no signature, no border",
    "guidance_scale": 7.5,
    "size": "1024x1024"
  }'

我收到了一個包含圖片陣列的 JSON 回應(依選項可為 base64 或 URL)。如果你偏好直接使用 URL,請設定輸出目標或儲存旗標(如果 API 支援的話)。我在測試階段使用 base64,並在本機解碼。

完整 Python 範例

這接近我某個週二早上執行的批次任務。結構簡單,剛好足以處理重試。

import os
import base64
import requests

API_KEY = os.getenv("WAVESPEED_API_KEY")
BASE_URL = "https://api.wavespeed.ai/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
}


def generate_image(prompt, negative_prompt, guidance_scale=7.5, size="1024x1024"):
    url = f"{BASE_URL}/images/generations"
    
    payload = {
        "model": "Z-Image-Base",
        "prompt": prompt,
        "negative_prompt": negative_prompt,
        "guidance_scale": guidance_scale,
        "size": size,
    }
    
    response = requests.post(
        url,
        headers={**headers, "Content-Type": "application/json"},
        json=payload,
        timeout=60
    )
    response.raise_for_status()
    
    data = response.json()
    b64_string = data["data"][0]["b64_json"]
    return base64.b64decode(b64_string)


if __name__ == "__main__":
    prompt = (
        "Editorial-style product photo of a ceramic mug on a linen table, soft morning light. "
        "35mm look, neutral color grading, no text, uncluttered background."
    )
    negative_prompt = (
        "no text, no watermark, no extra hands, no extra limbs, "
        "no logo, no signature, no border"
    )

    try:
        image_bytes = generate_image(prompt, negative_prompt)
        with open("output.png", "wb") as f:
            f.write(image_bytes)
        print("Saved output.png")
    except requests.HTTPError as e:
        print("HTTP error:", e.response.text if e.response else str(e))
    except Exception as e:
        print("Error:", str(e))

有一次任務在不穩定的 Wi‑Fi 環境下卡住,之後我加上了 60 秒的逾時設定。例外處理區塊雖然粗糙,但在正式環境中我會將狀態碼(429、503)對應到退避邏輯。

JavaScript/Node.js 範例

在 Node 中,我使用 fetch 搭配一個小型輔助函式。概念相同:保持驗證簡單,讓錯誤清晰浮現。

import fs from 'node:fs/promises';
import fetch from 'node-fetch';

const API_KEY = process.env.WAVESPEED_API_KEY;
const BASE_URL = 'https://api.wavespeed.ai/v1';

async function generateImage({
  prompt,
  negativePrompt,
  guidanceScale = 7.5,
  size = '1024x1024',
}) {
  const response = await fetch(`${BASE_URL}/images/generations`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'Z-Image-Base',
      prompt,
      negative_prompt: negativePrompt,
      guidance_scale: guidanceScale,
      size,
    }),
  });

  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`HTTP ${response.status}: ${errorText}`);
  }

  const json = await response.json();
  const base64String = json.data[0].b64_json;
  return Buffer.from(base64String, 'base64');
}

(async () => {
  try {
    const prompt = 
      'Editorial-style product photo of a ceramic mug on a linen table, soft morning light. ' +
      '35mm look, neutral color grading, no text, uncluttered background.';

    const negativePrompt = 
      'no text, no watermark, no extra hands, no extra limbs, ' +
      'no logo, no signature, no border';

    const imageBuffer = await generateImage({ prompt, negativePrompt });
    
    await fs.writeFile('node-output.png', imageBuffer);
    console.log('Saved node-output.png');
  } catch (err) {
    console.error('Error:', err.message);
  }
})();

這段程式碼跑通後,我就不再需要思考底層的管線問題了,這才是重點。Z-Image-Base API 沒有妨礙工作的進行。

非同步與同步模式

我兩種模式都試過了。同步模式適合單張圖片或快速確認。1024 方形輸出的平均延遲在低秒數範圍內。當我排隊生成 8–12 張圖片時,我就切換到非同步模式,這樣腳本就不會逐一阻塞等待。

非同步模式的流程很可預測:送出任務、取得 id、輪詢狀態 endpoint,等 state: "succeeded" 後再取回結果。我設定 2–3 秒的輪詢間隔,以及 2 分鐘的上限。在不穩定的網路環境中,非同步模式讓我免於逾時的困擾,因為我可以繼續輪詢而不需要重新提交任務。細節雖小,但在旅途中使用 Wi‑Fi 時差異巨大。

如果你的工作流程是互動式的(調整、查看、再調整),同步模式更方便。如果是批次或排程任務,非同步能讓管線更順暢,失敗時也能更優雅地處理。

錯誤處理

有兩種模式幫助我讓錯誤處理變得不那麼令人頭痛。

  • 速率限制(429):我使用帶有抖動的指數退避。從約 500ms 開始,上限約 20 秒,重試 5–6 次後停止。對於非同步任務,我只需重試狀態查詢,而不是重新排隊生成——除非 API 回報任務已遺失。
  • 驗證錯誤(400/422):通常來自不匹配的 Content-Type 或不支援的尺寸。當圖片編輯出現 422 時,幾乎都是我的 form-data 欄位名稱錯誤(imagereference_image 混淆)。我加了一個小型 schema 驗證,在送出請求前先檢查,藉此避免這個問題。

最後一點:我會記錄 modelguidance_scalesize,以及提示詞的雜湊值。當奇怪的結果出現時,我能完全重現它。這就是聳聳肩算了和真正修復的差別。

Z-Image-Base 的失敗率是否低於其他模型?很難說。我注意到的是,當它失敗時,錯誤訊息足夠具體,讓我不需要花時間猜測原因。這是很好的人體工學設計。