Guia Completo da API Z-Image-Base: Aplicação Prática de CFG + Prompt Negativo
Tutorial Completo da API Z-Image-Base: Ajuste do Parâmetro CFG, Uso de negative_prompt, Orientação por Imagem de Referência, Controle de Intensidade. Inclui exemplos de código em Python/cURL.
Olá, me chamo Dora. É incrível como um pequeno incômodo me empurrou para a API Z-Image-Base. Eu tinha um lote de imagens de referência, alguns textos que precisavam de uma aparência consistente e tempo insuficiente para ficar monitorando prompts. Continuava vendo pessoas ajustando configurações manualmente e postando resultados pontuais. Isso funciona para demos. Meu trabalho precisava de algo que eu pudesse executar duas vezes por semana sem surpresas. Então, ao longo de algumas sessões entre janeiro e fevereiro de 2026, configurei o Z-Image-Base, prestei atenção onde ele resistia, e anotei o que de fato o tornava confiável.
Este não é um guia de todos os parâmetros. São as partes que continuei ajustando, além de pequenos ajustes que reduziram o esforço mental. Se você está cercado de ferramentas de IA e quer apenas uma que se comporte bem, isso pode ajudar.
Configuração Básica da API
Obtendo a Chave de API do WaveSpeed
Me cadastrei e obtive uma chave de API pelo painel do WaveSpeed. Nada de surpreendente. Uma pequena observação: as permissões da chave eram delimitadas por projeto. Útil em fluxos de trabalho compartilhados, mas significa que você vai querer nomear os projetos claramente desde o início. Criei um projeto específico para experimentos com imagens para que logs e cotas não se misturassem com a produção.
Se você rotaciona chaves (eu faço isso mensalmente), o Z-Image-Base lidou com isso sem problemas. Troquei o segredo nas minhas variáveis de ambiente, executei o script novamente e não vi nenhum estado de autenticação remanescente. É assim que deveria funcionar, mas ainda senti um certo alívio quando funcionou na primeira tentativa.
Estrutura da URL do Endpoint
A base parecia uma configuração REST padrão com um seletor de modelo:
- Base:
https://api.wavespeed.ai - Caminho versionado:
/v1/images - Seletor de modelo:
model: "Z-Image-Base"
Na prática, enviei requisições POST para /v1/images/generations em execuções apenas com prompt, e /v1/images/edits quando passei uma imagem de referência. Prefiro caminhos claros a query strings densas, e isso combinava com minha forma de pensar. Se o seu roteamento for diferente, o nome do modelo ainda importa: o Z-Image-Base parecia um pouco mais conservador do que modelos mais chamados, o que gostei.
Configurações do Cabeçalho de Autenticação
Nada complicado aqui, mas a grafia exata importa:
Authorization: Bearer SUA_CHAVE_API_WAVESPEEDContent-Type: application/jsonpara apenas promptContent-Type: multipart/form-dataao fazer upload de uma imagem
Mantenho as chaves em .env e as carrego em tempo de execução. É entediante, e evita commits acidentais. Também: se você está executando scripts a partir de CI, defina a chave como um segredo mascarado e evite registrar requisições completas. Óbvio, mas vale dizer. Uma linha de log indevida pode te assombrar. Uma linha de log indevida pode te assombrar. De acordo com as melhores práticas de segurança do WaveSpeed, as chaves de API devem ser armazenadas em variáveis de ambiente, nunca expostas no código frontend, e rotacionadas regularmente.
Explicação Detalhada dos Parâmetros Principais
prompt - Método de Escrita de Prompt Direto
Não fiquei obcecado com o estilo do prompt. Com o Z-Image-Base, prompts diretos e simples funcionaram melhor do que prosa elaborada. Escrevi a intenção primeiro, as restrições depois:
- “Foto de produto estilo editorial de uma caneca de cerâmica sobre uma mesa de linho, luz suave da manhã.”
- Depois os detalhes: “Estética de 35mm, gradação de cor neutra, sem texto, fundo sem elementos.”
Mantive os verbos fora, a menos que precisasse de movimento. O modelo era estável quando eu era concreto: materiais, luz, sensação de lente, tipo de fundo. Ele se desviava quando eu adicionava atmosferas vagas. Se eu escrevesse “minimalismo aconchegante”, recebia um caos de velas. Quando escrevia “luz suave, uma fonte difusa, sem velas”, ele obedecia.
negative_prompt - Excluir Elementos Indesejados
Resisti aos negative prompts no começo, mas eles se tornaram meu trilho de segurança. Mantive uma base curta que reutilizava:
- “sem texto, sem marca d’água, sem mãos extras, sem membros extras, sem logo, sem assinatura, sem borda”
Adicionar isso reduziu o tempo de limpeza. Não resolveu todos os casos extremos (anéis ainda aparecem em canecas às vezes), mas baixou a taxa de estranhezas o suficiente para eu parar de re-renderizar para lotes pequenos. Quando precisava de ângulos de produto precisos, adicionei “sem perspectiva dramática, sem inclinação” e obtive fotos mais niveladas.
guidance_scale (CFG) - Controlar o Grau de Conformidade com o Prompt
Este parâmetro importou mais do que eu esperava. Minhas anotações:
- 5–6: relaxado, um pouco mais de textura e improvisação
- 7–8: confiável: o que usei na maioria das execuções
- 9+: conformidade literal, mas às vezes iluminação frágil e cor mais plana
Quando tinha uma boa imagem de referência, baixei o CFG para 6–7 e obtive micro-contraste mais bonito. Sem referência, 7,5 era minha mediana. De acordo com a documentação técnica do Z-Image, o modelo suporta CFG completo (Classifier-Free Guidance), oferecendo precisão para engenharia complexa de prompts. Acima de 9 parecia pedir a um amigo cuidadoso para ser ainda mais cuidadoso — não está errado, apenas ligeiramente sem vida.
image + strength - Orientação por Imagem de Referência
Essa dupla fez o trabalho pesado. Anexei um JPG de referência único e ajustei strength para controlar o quanto o modelo seguia:
- 0,25–0,35: toque leve: mantém paleta e estilo
- 0,45–0,6: aderência sólida: a composição permanece próxima
- 0,7+: quase cópia: útil para variações com pequenas mudanças de estilo
Não esperava que 0,5 fosse o ponto ideal, mas era. Estrutura suficiente para manter o layout, liberdade suficiente para ajustes de iluminação. Valores mais altos tornavam o modelo teimoso: se a fonte tinha uma sombra no lugar errado, o modelo se agarrava a ela. Comecei a indicar no prompt “sombra à esquerda da câmera” e reduzi a strength. Menos tentativas dessa forma.
Uma nota prática: redimensionei as imagens de referência para 1024 pixels no lado maior antes do upload. Dimensões consistentes me deram recortes e velocidades mais previsíveis. Também economizou um pouco de largura de banda ao longo de muitas iterações.
Implementação de Código
Teste Rápido com cURL
Quando estou configurando um novo endpoint, começo com cURL apenas para ver o formato da resposta e os códigos de erro.
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"
}'
Recebi de volta um payload JSON com um array de imagens (base64 ou URLs, dependendo das opções). Se preferir URLs diretas, defina um destino de saída ou flag de armazenamento se a API suportar. Fiquei com base64 nos testes e decodifiquei localmente.
Exemplo Completo em Python
Isso é próximo do que executei em um job de lote numa manhã de terça-feira. É simples, com estrutura suficiente para tentativas repetidas.
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))
Adicionei um timeout de 60s depois que um job travou em um Wi‑Fi instável. O bloco de exceção é direto, mas em produção mapeio os códigos de status (429, 503) para backoff.
Exemplo em JavaScript/Node.js
Para Node, usei fetch com um pequeno helper. Mesma ideia: manter a autenticação simples, exibir erros claramente.
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);
}
})();
Depois que isso funcionou, parei de pensar na infraestrutura, que é exatamente o objetivo. A API Z-Image-Base não atrapalhou.
Modo Assíncrono vs Síncrono
Experimentei os dois modos. O síncrono foi adequado para imagens únicas ou verificações rápidas. A latência ficou em poucos segundos em média para saídas quadradas de 1024. Quando enfileirei 8–12 renders, mudei para assíncrono para que meu script não bloqueasse em cada um.
O padrão assíncrono era previsível: envie um job, receba um id, faça polling em um endpoint de status, depois busque o resultado quando state: "succeeded". Defini um intervalo de polling de 2–3 segundos e um teto de 2 minutos. Em redes instáveis, o assíncrono me salvou de timeouts porque eu podia retomar o polling sem reenviar o job. Detalhe pequeno, grande diferença no Wi‑Fi de viagem.
Se seu fluxo de trabalho é interativo (ajustar, visualizar, ajustar), o síncrono é mais agradável. Se é em lote ou agendado, o assíncrono mantém o pipeline mais fluido e falha de forma mais elegante.
Tratamento de Erros
Dois padrões me ajudaram a manter os erros entediantes.
- Limites de taxa (429): Usei backoff exponencial com jitter. Comece em ~500ms, limite em ~20s, e pare após 5–6 tentativas. Com jobs assíncronos, simplesmente reexecutei a chamada de status em vez de re-enfileirar o render, a menos que a API indicasse que o job havia sido perdido.
- Erros de validação (400/422): Geralmente vinham de tipos de conteúdo incompatíveis ou tamanhos não suportados. Quando vi um 422 em edições de imagem, quase sempre era o nome do campo form-data errado (
imagevsreference_image). Adicionei uma pequena verificação de schema antes das requisições para evitar isso.
Mais uma nota: registrei model, guidance_scale, size e um hash do prompt. Quando algo estranho passava, eu conseguia reproduzi-lo exatamente. É a diferença entre dar de ombros e corrigir.
O Z-Image-Base falha menos do que outros modelos? Difícil dizer. O que notei foi que, quando falhava, as mensagens eram específicas o suficiente para não perder tempo adivinhando. Isso é uma boa ergonomia.





