HiAPI
Blog

Tutoriale

Come chiamare flux-2-klein-4b/text-to-image tramite l'API HiAPI: curl, Python e una richiesta funzionante

Un tutorial pratico per integrare il livello di immagini economico nella tua pipeline

Oct 31, 2026
平面玻璃风格封面图:数层半透明玻璃斜向叠压,把浅灰底场折射成冷蓝色带,构图安静克制。

Perché flux-2-klein-4b/text-to-image è adatto a carichi di lavoro sensibili ai costi

Non ogni pipeline di immagini ha bisogno del modello più pesante del catalogo. In produzione, una parte considerevole del traffico è ripetitiva: immagini prodotto, anteprime di varianti, miniature di elenchi di prodotti, card social generate dallo stesso template. Per questi scenari, flux-2-klein-4b/text-to-image è progettato come un livello volutamente più leggero: si scambia un po' di massima fedeltà con throughput e prevedibilità, e questo è di solito il compromesso giusto quando si generano migliaia di asset in batch pianificati.

Due categorie di workload ne beneficiano maggiormente:

  • Immagini prodotto per e-commerce. Di solito hai una descrizione base pulita ("tazza in ceramica opaca, 350 ml, grigio caldo, su sfondo bianco senza giunte") e devi generare numerose varianti di rendering che coprano colori, angolazioni e composizione. La coerenza conta più dell'espressività artistica.
  • Generazione in batch per interfacce interne o long-tail. Banner di categoria, creatività per test A/B, immagini segnaposto per liste in bozza: su questi asset il miglioramento marginale della qualità non giustifica un costo di esecuzione più alto.

Quando produci visual principali, texture fini o composizioni che sono esse stesse il prodotto, scegli un livello più pesante. Quando volume di generazione, latenza e costo per immagine guidano la decisione, scegli flux-2-klein-4b/text-to-image. Il resto di questo tutorial utilizza questo livello end-to-end: struttura della richiesta, chiamata curl, funzione di supporto Python, strategia di aspect ratio e ciclo di vita asincrono.

Preparazione prima di inviare la richiesta

Prima della prima chiamata, devi stabilire tre cose.

1. Una chiave API da HiAPI

Crea la chiave nella console HiAPI. Ogni richiesta descritta qui si autentica con quella chiave, e la chiave è l'unica credenziale di cui hai bisogno: non esiste un processo separato di registrazione per modello.

2. Tenere la chiave fuori dal controllo del codice sorgente

Tratta la chiave come qualsiasi altro segreto. Una pratica collaudata:

export HIAPI_API_KEY="your-key-here"

Poi leggila dall'ambiente nella shell e in Python. Non commetterla mai e, se usi un loader di dotfile, aggiungi .env a .gitignore. Se la chiave viene esposta, ruotala nella console invece di cercare di ripulire la cronologia.

3. Confermare l'identificatore del modello

La stringa dell'identificatore viene usata così com'è nel corpo della richiesta e, in alcune configurazioni, anche nell'URL:

flux-2-klein-4b/text-to-image

Copiala esattamente: sia 4b sia il suffisso /text-to-image fanno parte del nome. Un errore di battitura qui è la causa più comune di errori 404 o "unknown model". Una volta che la chiave è nell'ambiente e l'identificatore è confermato, puoi costruire il payload.

Composizione di una richiesta a flux-2-klein-4b/text-to-image

Le richieste text-to-image su HiAPI sono volutamente snelle. Fornisci l'identificatore del modello e un payload di parametri di generazione; la risposta è o il risultato o un handle di job, a seconda di come è configurato l'endpoint del modello.

I campi più importanti

  • model — l'identificatore esatto, flux-2-klein-4b/text-to-image.
  • prompt — una stringa che descrive l'immagine. È il campo che influisce maggiormente sulla qualità dell'output; concentra l'attenzione qui prima di modificare qualsiasi altra cosa.
  • Dimensioni o aspect ratio — come specifichi l'inquadratura dell'output. Preferisci una specifica in forma di aspect ratio rispetto a coppie di pixel hardcoded, perché resta stabile anche se il comportamento della risoluzione sottostante cambia.

Come appare la risposta

La risposta assume due forme, e il tuo client dovrebbe gestirle entrambe:

  1. Payload sincrono — la risposta include direttamente la posizione dell'immagine generata (un URL).
  2. Payload di job asincrono — la risposta include un identificatore di job e uno stato (pending, processing, succeeded, failed sono stati tipici). Poi interroghi l'endpoint di stato con quell'identificatore finché non raggiunge uno stato terminale e il payload porta la posizione dell'output.

Non inventare parametri che non puoi verificare. Se un campo non fa parte della richiesta documentata del modello, non includerlo: i campi sconosciuti sono la seconda causa più comune di errori 400 confusi. Inizia con model, prompt e aspect ratio, ottieni prima un'immagine funzionante, poi aggiungi uno per uno i parametri opzionali e controlla l'output dopo ogni modifica.

La tua prima chiamata curl funzionante

Ecco una richiesta completa che puoi incollare nel terminale. Presuppone che HIAPI_API_KEY sia stata esportata come sopra.

curl -sS -X POST "https://api.hiapi.ai/v1/images/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-2-klein-4b/text-to-image",
    "prompt": "Studio product photo of a matte ceramic mug, warm grey, soft diffused light, seamless white background, centered composition",
    "aspect_ratio": "1:1"
  }'

Passala a un formattatore JSON (| jq .) per leggere la risposta. Vedrai direttamente l'URL dell'immagine o un oggetto job con id e status.

Interpretare il risultato

  • Se ottieni un URL immagine, aprilo nel browser. Questo conferma che chiave, identificatore del modello e prompt funzionano.
  • Se ottieni un oggetto job, annota l'id: lo interrogherai nella sezione successiva.

Diagnosticare i guasti comuni

  • 401 / 403 — chiave mancante, malformata o non passata tramite l'header Authorization: Bearer. Verifica che la variabile d'ambiente sia effettivamente esportata nella shell in cui esegui curl.
  • 404 o "unknown model" — identificatore errato. Deve essere esattamente flux-2-klein-4b/text-to-image.
  • 400 con messaggio di validazione — di solito prompt mancante, un nome di parametro non supportato o un aspect ratio non nell'insieme accettato. Riduci il payload ai tre campi principali e riprova.
  • 429 — stai inviando richieste più velocemente di quanto il tuo livello consenta. Aggiungi un backoff invece di riprovare in un ciclo serrato.

Una volta che curl funziona, hai una richiesta nota e funzionante da confrontare quando qualcosa va storto nella versione Python.

Portare la stessa richiesta in Python

La versione Python è un sottile wrapper attorno allo stesso payload. Organizzala come funzione, così il resto della pipeline può chiamarla senza duplicare la logica HTTP.

import os
import time
import requests

API_BASE = "https://api.hiapi.ai/v1"
MODEL = "flux-2-klein-4b/text-to-image"

def generate_image(prompt: str, aspect_ratio: str = "1:1") -> dict:
    """Submit a text-to-image job and return the parsed response."""
    api_key = os.environ["HIAPI_API_KEY"]
    payload = {
        "model": MODEL,
        "prompt": prompt,
        "aspect_ratio": aspect_ratio,
    }
    response = requests.post(
        f"{API_BASE}/images/generations",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json=payload,
        timeout=60,
    )
    if response.status_code >= 400:
        # Surface the server's message rather than a bare status code.
        raise RuntimeError(f"HiAPI error {response.status_code}: {response.text}")
    return response.json()

Alcune abitudini di efficacia immediata:

  • Leggi la chiave dall'ambiente all'interno della funzione, non al momento dell'import, così lo stesso modulo funziona in notebook, script e attività pianificate.
  • Controlla esplicitamente il codice di stato e includi il corpo della risposta nell'eccezione. I messaggi di validazione di HiAPI ti dicono quale campo è errato; un raise_for_status() nudo lo nasconde.
  • Imposta un timeout. Senza timeout, una connessione bloccata può sospendere indefinitamente il processo di lavoro.
  • Mantieni il payload come dict, così puoi registrarlo, confrontarlo ed estendere i parametri opzionali senza riscrivere la formattazione delle stringhe.

Ora un driver minimo:

result = generate_image(
    "Studio product photo of a matte ceramic mug, warm grey, "
    "soft diffused light, seamless white background, centered composition"
)
print(result)

Scegliere aspect ratio che resistono in produzione

L'aspect ratio è il parametro più probabile che causi rilavorazioni in una fase successiva, perché i sistemi a valle presumono l'inquadratura. Decidilo per interfaccia, non per richiesta.

Una mappatura pratica

  • Quadrato (1:1) — elenchi di marketplace, griglie di prodotti, avatar e posizioni per miniature. È il default sicuro per l'e-commerce, perché la maggior parte delle tile prodotto è quadrata e il ritaglio risulta scadente.
  • Verticale (3:4 o 4:5) — posizioni nei feed social e immagini prodotto in stile lookbook. Offre spazio a prodotti verticali come bottiglie e abbigliamento senza aggiungere bande nere.
  • Orizzontale (16:9) — banner, strisce hero, intestazioni email, miniature video.

Perché bloccare il rapporto a monte

Se il rapporto viene scelto al momento del rendering dal codice che capita chiami l'API, ottieni un catalogo prodotto in cui metà delle tile sono quadrate e metà verticali, e paghi una rigenerazione per sistemarlo. Invece, codifica il rapporto nel tuo modello di contenuto — un campo surface o placement che si mappa deterministicamente su un rapporto — e genera da quel campo. Usa 1:1 dove il ritaglio è tollerabile; usa il rapporto richiesto dal layout dove il layout è fisso.

La stessa disciplina vale per i prompt: includi i suggerimenti di inquadratura ("composizione centrata", "prodotto intero nel frame", "spazio vuoto a sinistra per il testo") nel template del prompt, non in stringhe temporanee per singola chiamata. I template fanno sì che mille immagini generate sembrino provenire dalla stessa pipeline, ed è esattamente ciò di cui ha bisogno un catalogo prodotto.

Un avvertimento: non ogni modello accetta ogni rapporto. Invia una volta il rapporto scelto, conferma il successo e solo allora estendilo all'intero batch.

Interrogare i job asincroni fino al completamento

Quando flux-2-klein-4b/text-to-image restituisce un handle di job invece di un'immagine, trattalo come una macchina a stati. Il flusso è: invia → ricevi l'ID del job → interroga lo stato → stato terminale → leggi l'output.

def wait_for_job(job_id: str, timeout_s: int = 300, interval_s: int = 2) -> dict:
    api_key = os.environ["HIAPI_API_KEY"]
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        response = requests.get(
            f"{API_BASE}/jobs/{job_id}",
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=30,
        )
        response.raise_for_status()
        job = response.json()
        status = job.get("status")
        if status == "succeeded":
            return job
        if status == "failed":
            raise RuntimeError(f"Job {job_id} failed: {job.get('error')}")
        time.sleep(interval_s)
    raise TimeoutError(f"Job {job_id} did not finish in {timeout_s}s")

Gestire ogni stato

  • pending / processing — continua ad attendere. Inizia con intervalli brevi e valuta un backoff delicato (ad esempio, aumentando il tempo di sonno fino a un limite) per non martellare l'endpoint di stato durante code lunghe.
  • succeeded — il payload ora contiene la posizione dell'output. Interrompi immediatamente il polling.
  • failed — non riprovare alla cieca. Registra il messaggio di errore; se è un problema di prompt o parametri, reinviare la stessa richiesta fallirà allo stesso modo.

Sapere quando fermarsi

Vincola sempre il ciclo a una scadenza a orologio. Un processo di lavoro che interroga per sempre è un processo di lavoro che perde risorse. In caso di timeout, esponi l'ID del job per l'ispezione manuale: se il job riesce in seguito, puoi comunque recuperare l'output. Per i batch, esegui più job in concorrenza e interrogali insieme, invece di serializzare invio e attesa per ogni immagine.

Scaricare e archiviare gli output

Le immagini generate appaiono nella risposta di generazione o del job come posizioni recuperabili. Recuperale lato server e poi rendile persistenti da te: non collegare direttamente l'URL restituito nelle pagine prodotto, perché è un artefatto di consegna, non il tuo livello di storage.

def download_image(url: str, path: str) -> str:
    response = requests.get(url, timeout=120)
    response.raise_for_status()
    with open(path, "wb") as f:
        f.write(response.content)
    return path

Usare uno schema di denominazione prevedibile

Percorsi come images/{surface}/{sku}/{variant}-{ratio}.png ti danno tre cose: gli asset sono raggruppati naturalmente per prodotto, l'interfaccia ti dice quale inquadratura è stata richiesta, e il rapporto nel nome file rende evidenti i duplicati accidentali. Se rigeneri una variante dello stesso SKU, includi nel nome file un breve hash del prompt, così una nuova esecuzione non sovrascrive silenziosamente tentativi precedenti che potresti voler confrontare.

Chiudere il cerchio

Registra l'ID del job insieme al file archiviato, in un manifest, in una riga di database o in un file affiancato. Quando un sistema a valle segnala un'immagine scadente, l'ID del job è ciò che ti permette di recuperare il prompt e i parametri originali. Insieme ai nomi file content-addressed, questo ti dà una traccia di audit riproducibile dall'asset archiviato fino alla richiesta esatta che l'ha prodotto.

Una volta collegati invio, polling e download, flux-2-klein-4b/text-to-image diventa un normale passo della tua pipeline: accoda il lavoro, interroga con una scadenza, archivia con nomi stabili. Da lì, scalare è solo una questione di concorrenza e template, non di nuovo codice.

Inizia a creare con artefatti IA persistenti

Ottieni la tua chiave API e chiama modelli di immagini, video e audio tramite un'unica API basata sui task.

Leggi la documentazione API