← 博客

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 脚本中调用,请将密钥设置为掩码密钥,并避免记录完整请求。这是常识,但值得一提。一行日志泄漏可能带来很大麻烦。根据 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 技术文档,该模型支持完整的无分类器引导(CFG),为复杂的提示词工程提供精准控制。超过 9 就像让一个已经很谨慎的朋友更加谨慎——不是错的,只是少了点生气。

image + strength - 参考图引导

这一对参数承担了最重要的工作。我上传单张参考 JPG,通过调整 strength 来控制模型的参考程度:

  • 0.25–0.35:轻度参考,保留配色和整体氛围
  • 0.45–0.6:中度参考,构图保持接近
  • 0.7 以上:近乎复制,适合在小幅风格改动下生成变体

我没想到 0.5 会成为最佳甜点,但事实就是如此。足够的结构约束来保留布局,又留有足够的自由度来调整光线。strength 越高,模型越”固执”:如果原图中有个位置不对的阴影,模型会死死保留它。我后来开始在提示词中加入”shadow on camera-left”(阴影在画面左侧),同时降低 strength,反而减少了重试次数。

一个实用小贴士:上传前我会将参考图的长边缩放到 1024 像素。统一的尺寸让裁剪结果和生成速度更加可预测,多次迭代下来也节省了不少带宽。

代码实现

cURL 快速测试

接入新接口时,我习惯先用 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,轮询状态接口,等状态变为 state: "succeeded" 后获取结果。我设置了 2–3 秒的轮询间隔和 2 分钟的超时上限。在网络不稳定的情况下,异步模式帮我避免了超时问题,因为我可以恢复轮询而无需重新提交任务。细节不大,但在出行途中用 Wi-Fi 工作时差别显著。

如果你的工作流是交互式的(调整、查看、再调整),同步模式更顺手。如果是批量处理或定时任务,异步模式能让流水线更流畅,出错时也更容易处理。

错误处理

有两种模式帮助我把错误处理变得”无聊”(即稳定可预期)。

  • 频率限制(429):我使用带抖动的指数退避策略。从约 500ms 开始,上限约 20 秒,最多重试 5–6 次。对于异步任务,除非 API 显示任务不存在,否则我只重试状态查询,而不是重新排队渲染。
  • 参数验证错误(400/422):通常来自内容类型不匹配或尺寸不支持。每次在图片编辑时看到 422,几乎都是因为 form-data 字段名写错了(image 还是 reference_image)。我在请求前加了一个简单的 schema 校验来预防这个问题。

还有一点:我记录了 modelguidance_scalesize 以及提示词的哈希值。当出现奇怪的结果时,我可以完整复现。这就是”耸耸肩算了”和”真正解决问题”之间的区别。

Z-Image-Base 的失败率是否比其他模型低?这很难说。但我注意到的是,当它出错时,错误信息足够具体,让我不会浪费时间猜测原因。这是很好的用户体验设计。