HiAPI
Blog

Tutoriale

Come chiamare recraft-v4-styles-pro/text-to-image sull'API hiapi: curl e Python

Oct 31, 2026
hiapi 博客封面:近黑底色上有序排列的薄荷绿数据点阵由疏到密渐变,呈半调网点质感,另有点缀深青色,画面无文字。

Cosa fa questo endpoint e quando usarlo

recraft-v4-styles-pro/text-to-image converte i prompt testuali in immagini, con una caratteristica distintiva: la consapevolezza dello stile. Puoi guidare il linguaggio visivo del risultato tramite riferimenti di stile, invece di affidarti solo alla formulazione del prompt. È una scelta pratica quando l'output deve mantenere una sensazione coerente su molte generazioni, e non solo apparire bene in una o due.

Gli sviluppatori lo usano spesso in questi scenari:

  • Materiali coerenti con il brand: immagini chiave, card social e varianti pubblicitarie che devono rientrare tutti nello stesso sistema visivo.
  • Mockup di prodotto e marketing: ottimizzare ripetutamente il prompt, fissare lo stile e produrre una serie di varianti coerenti con il brand.
  • Passaggi di pipeline: la generazione è una fase di un'automazione più ampia, in cui un altro servizio consuma le immagini salvate.

C'è una caratteristica che determina come va scritto ogni esempio di codice seguente: la generazione delle immagini è asincrona. La richiesta invia il task e restituisce subito; l'immagine appare più tardi. Devi scrivere un passaggio di invio e un passaggio di polling, trattandoli come due preoccupazioni separate.

Preparare le credenziali hiapi e le basi della richiesta

Tutte le chiamate passano attraverso l'interfaccia unificata degli endpoint di hiapi, quindi prima della prima richiesta servono tre cose:

  1. Una chiave API, dal tuo account hiapi. Trattala come qualsiasi altro segreto: caricala da una variabile d'ambiente, non codificarla mai direttamente in uno script che potresti condividere.
  2. L'identificatore del modello, che deve corrispondere esattamente a quello pubblicato: recraft-v4-styles-pro/text-to-image.
  3. Uno strumento compatibile con HTTP: curl per esplorare e una libreria HTTP per qualsiasi scenario persistente.
export HIAPI_API_KEY="your-key-here"

Convenzioni da interiorizzare presto:

  • Usa Content-Type: application/json quando invii un corpo JSON.
  • Autenticati con un header bearer token.
  • Mantieni l'id del modello, il prompt e i riferimenti di stile come campi separati nel payload, invece di stipare tutto in un'unica stringa: così i passaggi di polling e i log saranno più facili da capire.

Per i nomi esatti degli header, l'URL di base e le definizioni attuali dei campi, consulta la documentazione di riferimento dell'API hiapi per questo modello; considera questo tutorial come la forma della chiamata e la documentazione come la fonte autorevole per i nomi.

Una richiesta curl funzionante

Quella che segue è la chiamata di invio. Leggila su tre livelli: trasporto, autenticazione e corpo della richiesta.

curl -sS -X POST "$HIAPI_BASE_URL/generate" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "recraft-v4-styles-pro/text-to-image",
    "prompt": "minimalist product photo of a ceramic mug on a linen surface, soft daylight",
    "style_references": []
  }'

Spiegazione riga per riga:

  • -X POST: invia il task, non recupera.
  • Authorization: Bearer ...: il token proviene da una variabile d'ambiente, quindi il comando può essere incollato in sicurezza nel terminale e condiviso in sicurezza una volta rimossa la variabile.
  • -d '{...}': il corpo JSON. model è l'identificatore esatto. prompt è il testo libero che descrive la scena. style_references è il punto di aggancio per il controllo dello stile, di cui parleremo tra poco.
  • -sS: modalità silenziosa per la barra di avanzamento, ma mostra comunque gli errori, così le chiamate fallite sono visibili.

Una risposta riuscita è una conferma, non un'immagine: ottieni l'identificatore del task e lo stato. Annota quell'identificatore: è l'unico handle necessario per il polling. Se stai esplorando in modo interattivo, passa la risposta a un formattatore JSON per rendere più evidenti l'id del task e lo stato.

Passare i riferimenti di stile insieme al prompt

Il modello mentale è semplice: il prompt dice cosa, i riferimenti di stile dicono come dovrebbe apparire. Mantienili separati nel payload e conserverai la flessibilità: puoi rieseguire lo stesso prompt con più set di stili per confrontare i risultati.

{
  "model": "recraft-v4-styles-pro/text-to-image",
  "prompt": "ceramic mug on a linen surface, soft daylight",
  "style_references": [
    "https://your-bucket.example.com/styles/mug-ref-01.jpg",
    "https://your-bucket.example.com/styles/mug-ref-02.jpg"
  ]
}

Consigli pratici:

  • Inizia senza riferimenti. Esegui prima il prompt da solo. Poi aggiungi un riferimento e osserva la differenza, quindi due. Cambiare una cosa alla volta dà molta più informazione che usare l'intero set di stili al primo tentativo.
  • Mantieni i riferimenti accessibili. Ospitali dove il servizio può recuperarli in modo affidabile, come un bucket pubblico o un URL firmato con validità ampia, non un link che scade dopo pochi minuti.
  • Mantieni il set coerente. Riferimenti tra loro coerenti (illuminazione, palette, texture simili) tendono a produrre risultati più stabili rispetto a un insieme eterogeneo, che richiede al modello di conciliare contraddizioni.
  • Versiona i riferimenti. Conservali sotto chiavi stabili. Quando tra un mese l'output sarà problematico, dovrai sapere esattamente quali file di riferimento sono stati usati.

Consulta la documentazione di riferimento hiapi per questo modello per confermare se i riferimenti di stile vengono passati come URL, risorse caricate o preset con nome, e quali limiti esistono su numero e formato.

La stessa chiamata in Python

La chiamata curl si converte direttamente. Incapsulala in piccole funzioni per riutilizzarla come fase della pipeline.

import os
import requests

HIAPI_BASE_URL = os.environ["HIAPI_BASE_URL"]
HIAPI_API_KEY = os.environ["HIAPI_API_KEY"]


def submit_generation(prompt: str, style_references: list[str] | None = None) -> str:
    """Invia un task di text-to-image e restituisce l'id del task."""
    payload = {
        "model": "recraft-v4-styles-pro/text-to-image",
        "prompt": prompt,
        "style_references": style_references or [],
    }
    response = requests.post(
        f"{HIAPI_BASE_URL}/generate",
        headers={
            "Authorization": f"Bearer {HIAPI_API_KEY}",
            "Content-Type": "application/json",
        },
        json=payload,
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()
    return data["job_id"]

Note di progettazione:

  • Imposta sempre un timeout. Un invio che resta appeso all'infinito blocca il tuo worker in modo tanto efficace quanto un crash.
  • raise_for_status() converte le risposte non-2xx in eccezioni che puoi catturare e registrare nei log, invece di proseguire silenziosamente con un corpo di risposta malformato.
  • Restituisci solo l'id. L'id del task è il contratto tra invio e polling. Tenere il resto della risposta fuori dal codice chiamante renderà più semplice la sezione successiva.

Verifica nella documentazione di riferimento hiapi il nome effettivo del campo della risposta e adegua di conseguenza data["job_id"]: la denominazione dei campi è l'aspetto più probabile in cui differirai dagli esempi di questo articolo.

Eseguire il polling dello stato di completamento del task

La generazione richiede tempo. Esegui il polling a intervalli regolari, fermati allo stato terminale e rinuncia alla fine.

import time


def wait_for_job(job_id: str, timeout: float = 300, interval: float = 3) -> dict:
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        response = requests.get(
            f"{HIAPI_BASE_URL}/jobs/{job_id}",
            headers={"Authorization": f"Bearer {HIAPI_API_KEY}"},
            timeout=30,
        )
        response.raise_for_status()
        job = response.json()

        status = job["status"]
        if status == "succeeded":
            return job
        if status == "failed":
            raise RuntimeError(f"Job {job_id} failed: {job.get('error')}")

        time.sleep(interval)
    raise TimeoutError(f"Job {job_id} did not finish within {timeout}s")

Gli aspetti meno ovvi:

  • Tre esiti, non due. In attesa, riuscito, fallito. Tratta qualsiasi stato non riconosciuto come in attesa e registra una riga di log, così uno stato appena aggiunto non farà crashare il worker.
  • Un'unica scadenza per l'intera attesa. La scadenza basata su time.monotonic() non risente degli aggiustamenti dell'orologio, a differenza dell'aritmetica sull'orologio di sistema.
  • Non inviare richieste troppo frequentemente. Per la generazione di immagini, qualche secondo tra un controllo e l'altro è sufficiente. Se devi eseguire il polling più rapidamente, aggiungi un backoff tra i tentativi invece di accorciare l'intervallo.
  • Imponi un timeout. Un task che non termina mai deve manifestarsi come un errore che genera un avviso, non come un ciclo che continua fino a quando il container viene ucciso.

Se esegui molti task, inviali in batch ed esegui il polling in modo concorrente, usando un event loop o un pool di thread con intervalli scaglionati, invece di generare un poller per ogni task in un ciclo stretto.

Scaricare e salvare l'output

Un task completato ti fornisce un riferimento all'immagine, di solito un URL. Scaricala tempestivamente, perché questi link possono avere una scadenza.

def save_image(job: dict, path: str) -> None:
    url = job["output"]["image_url"]
    for attempt in range(3):
        try:
            with requests.get(url, stream=True, timeout=60) as r:
                r.raise_for_status()
                with open(path, "wb") as f:
                    for chunk in r.iter_content(chunk_size=8192):
                        f.write(chunk)
            return
        except requests.RequestException:
            if attempt == 2:
                raise
            time.sleep(2 ** attempt)

Pratiche che vale la pena adottare in produzione:

  • Download in streaming. Le immagini generate non sono piccole; caricarle interamente in memoria senza motivo è uno spreco.
  • Scrivi su un percorso temporaneo, poi rinomina. Un crash a metà scrittura non deve lasciare un file troncato nel punto in cui la pipeline si aspetta un'immagine valida.
  • Riprova il download, non la generazione. Riprovare un recupero instabile da un bucket costa poco; sprecare una generazione no. Limita il numero di tentativi e usa un backoff esponenziale.
  • Persisti l'id del task insieme al file. Quando qualcuno chiede da dove viene un'immagine, la risposta deve richiedere una sola query, non una ricerca nei log.

Per l'object storage, sostituisci open() con l'upload in streaming del tuo SDK e mantieni la stessa struttura di retry.

Errori, retry e controlli di buon senso sui costi

Le modalità di errore che incontrerai per prime, e come gestire ciascuna:

  • 401 / errori di autenticazione: chiave mancante, digitata male o non esportata nella shell che esegue lo script. Controlla l'ambiente prima di toccare il payload.
  • Errori di validazione 4xx: di solito un id del modello digitato male, un prompt mancante o un riferimento di stile malformato. Registra il corpo della risposta alla lettera; i messaggi di validazione sono la via più rapida alla soluzione qui.
  • 429 / limite di frequenza: usa un backoff con jitter, non un nuovo tentativo immediato. Impostare una coda prima della funzione di invio è meglio di una tempesta di retry.
  • Timeout del task: è scattata la scadenza del polling. Decidi deliberatamente se reinviare; un reinvio cieco raddoppia la spesa senza aumentare il tasso di successo.
  • Errori di rete transitori: riprova invio e download con un backoff esponenziale limitato. Riprova liberamente i download falliti; con cautela le generazioni.

Disciplina sui costi, in termini pratici:

  • La fatturazione segue il lavoro effettivamente eseguito dal modello, quindi i task falliti e i batch abbandonati sono costi nascosti. Registra ogni invio con l'hash del prompt e l'id del task, per poter rendicontare l'utilizzo in seguito.
  • Itera con i prompt più economici possibile. Metti a punto formulazione e riferimenti di stile con esecuzioni piccole e rapide, poi investi in batch grandi.
  • Deduplica. Se lo stesso prompt e lo stesso set di stili vengono richiesti due volte, servi il risultato del primo dalla tua cache.
  • Aggiungi un limite di concorrenza rigido nel worker. È più facile alzare un limite che spiegare una fattura inaspettata.

Trattando invio, polling e salvataggio come tre funzioni separate e testabili, questo endpoint si integra in modo pulito in qualsiasi pipeline. Per i nomi esatti dei campi, gli stati e i prezzi attuali, consulta la pagina del modello recraft-v4-styles-pro/text-to-image su hiapi prima dell'integrazione.

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