Tutorial sull’API di Seedream 5.5: generazione, modifiche e migrazione

Genera e modifica immagini con l’API di Seedream 5.5: ID del modello, stato delle attività, download autenticati, polling asincrono e insidie della migrazione.

AIHubMix10 min di lettura
Tutorial sull’API di Seedream 5.5: generazione, modifiche e migrazione

Una migrazione utile a Seedream 5.5 riguarda il flusso di gestione dei file, non soltanto la sostituzione del nome del modello: genera un’immagine, esamina l’attività restituita, salva l’immagine e poi invia i byte salvati come riferimento per una modifica.

Seedream 5.5 su AIHubMix usa attualmente doubao-seedream-5-5 e POST /ai/v1/images/generations. Questo tutorial crea un’immagine di prodotto con una tazza in ceramica, poi richiede una modifica limitata al colore.

Ambito: documentazione consultata il 12 novembre 2026. Il codice è stato sottoposto solo a controlli locali della sintassi e delle funzioni di supporto offline; non è stata eseguita alcuna richiesta di generazione. Questi controlli non attestano la qualità dei risultati, la fedeltà delle modifiche, la latenza o l’importo effettivo di una fattura.

1. Prepara una richiesta breve ed esplicita

Usa Python 3.10+ con requests. In Bash, installa la dipendenza e inserisci la chiave senza salvarne il valore nella cronologia della shell:

python3 -m pip install requests
read -r -s -p 'AIHubMix API key: ' AIHUBMIX_API_KEY
printf '\n'
export AIHUBMIX_API_KEY

Per il codice distribuito, inietta la variabile d’ambiente tramite il tuo gestore di segreti. Non inserire la chiave nei file sorgente, negli esempi di richieste, nei log, nei notebook o nel codice eseguito nel browser. Prima di entrambe le POST, attiva la funzionalità delle attività per l’account, come richiesto dalla guida alle attività asincrone. Questo prerequisito si applica agli endpoint nativi per le attività multimediali /ai/v1, compresa l’attesa sincrona; è distinto dalla scelta di eseguire il lavoro in background.

Consulta lo schema attuale degli endpoint del modello, selezionando la voce in base a path, non alla posizione nell’array. I vincoli specifici del modello prevalgono sull’elenco condiviso dei parametri.

Impostazione Valore usato qui
Modello doubao-seedream-5-5
Endpoint POST /ai/v1/images/generations
Corpo JSON piatto
Dimensione 2048x2048
Numero di immagini n = 1
Formato del file png
Formato della risposta url

Lo schema richiede model e un prompt non vuoto, limita n a 1 ed elenca png e jpeg tra i formati di output. Accetta image come URL, input Base64 o oggetto {url}; images accetta un array con un massimo pubblicato di 14 riferimenti. Questo limite non è stato verificato a runtime. L’esempio usa un solo riferimento e specifica esplicitamente la dimensione predefinita, senza oggetti esterni input né estensioni extra.

2. Genera, esamina l’attività e salva il PNG

La documentazione dell’API unificata per le immagini definisce una risposta dell’attività con id, object: image, model, status, output e error. Non interpretarla come il formato legacy data[0].url.

Leggi prima il breve flusso di lavoro; la configurazione completa e la funzione di supporto per il download si trovano nell’Appendice espandibile qui sotto. Prima di eseguire questi esempi, carica una volta il blocco dell’appendice nella stessa sessione Python. Definisce settings, api_json e collect senza inviare una richiesta di generazione di immagini. Poi esegui i brevi blocchi nell’ordine indicato. Ogni POST è un’azione a pagamento distinta; non eseguirla di nuovo per rimediare a una risposta mancante o a un download non riuscito.

Invia la richiesta di generazione una sola volta

generation = {
    **settings,
    "prompt": "Product photograph of one matte blue ceramic mug on a cream tabletop, "
              "soft side lighting, plain warm-gray background, no text or logos.",
}
task = api_json("POST", IMAGES + "/generations", generation)

Esamina l’attività, poi salva il PNG

Se ometti async, l’attesa è sincrona. Una risposta HTTP 200 può comunque contenere status: failed. La funzione di supporto salva l’ID dell’attività prima di esaminarne lo stato: solo completed procede al download; failed, cancelled e gli stati sconosciuti interrompono l’esecuzione. Per pending e in_progress occorre esaminare l’attività esistente, non avviare un’altra generazione.

collect(task, "mug-blue")

Questa singola chiamata usa la chiave con cui è stata creata l’attività per recuperare il risultato completato, verifica i byte PNG e salva il file mug-blue.png. Non riprova automaticamente la creazione e rifiuta host di download o reindirizzamenti imprevisti prima di inoltrare la chiave. L’implementazione completa è nell’appendice; si tratta di un comportamento descritto nella documentazione, non di un risultato di generazione verificato.

La guida del modello indica che gli URL dei risultati rimangono validi per circa 30 minuti. Scarica il file tempestivamente usando la stessa intestazione Bearer e conserva i byte autonomamente. expires_at: null non garantisce una conservazione permanente. Se b64_json è valorizzato, decodificalo invece di scaricare un URL.

3. Modifica il file locale, non il suo URL di download protetto

Esamina personalmente l’immagine salvata prima di spendere per una modifica. Un content_url che il tuo client autenticato riesce a scaricare non è necessariamente un URL pubblico accessibile al fornitore di immagini. Ricarica il PNG locale come Data URI:

reference = Path("mug-blue.png").read_bytes()
if not reference.startswith(b"\x89PNG\r\n\x1a\n"):
    raise SystemExit("The editing reference must be the saved PNG.")
edit = {
    **settings,
    "prompt": "Change only the mug color from blue to forest green. Preserve the mug shape, "
              "camera angle, tabletop, background, lighting, and shadows.",
    "image": "data:image/png;base64," + base64.b64encode(reference).decode("ascii"),
}
task = api_json("POST", IMAGES + "/generations", edit)
collect(task, "mug-green")

Questa richiesta chiede di preservare l’immagine, ma non dimostra che tale preservazione sia avvenuta. Esamina il risultato prima di un altro ciclo a pagamento. L’intera richiesta JSON, inclusa la codifica inline, deve rientrare in 32 MiB; si applicano anche i limiti multimediali specifici del modello. Un URL di immagine realmente pubblico e raggiungibile dal fornitore è un’altra opzione di input accettata.

4. Facoltativo: attesa asincrona e recupero dopo un’interruzione

Il prerequisito relativo all’account indicato nella sezione 1 è distinto dalla modalità di esecuzione. 403 async_not_enabled significa che occorre attivare la funzionalità delle attività nella console. Solo l’esecuzione in background è facoltativa.

Se preferisci la generazione in background, crea lo stesso dizionario generation, poi usa le due righe qui sotto al posto sia della riga sincrona task = api_json(...) sia della chiamata separata a collect(...). Scegli la modalità prima dell’invio; non eseguire entrambe le versioni:

task = api_json("POST", IMAGES + "/generations", {**generation, "async": True})
collect(task, "mug-blue", poll=True)

La funzione di supporto interroga GET /ai/v1/images/{id} circa ogni 15 secondi fino al raggiungimento di uno stato terminale. È la frequenza di polling consigliata nella documentazione, non un intervallo imposto dal server. I webhook richiedono async: true; la loro implementazione di un ricevitore non rientra nell’ambito di questo tutorial.

Se la raccolta si è interrotta, se necessario ricarica in una nuova sessione solo il blocco condiviso di configurazione e funzioni di supporto dell’appendice, non un blocco di creazione. Se hai salvato un ID, riprendi senza alcuna POST:

task_id = Path("mug-blue.task-id").read_text(encoding="utf-8").strip()
task = api_json("GET", IMAGES + "/" + quote(task_id, safe=""))
collect(task, "mug-blue", poll=True)

Per recuperare la modifica, usa il prefisso corrispondente mug-green. Se la risposta di creazione è scomparsa prima che venisse salvato un ID, esamina invece le attività recenti:

recent = api_json("GET", IMAGES + "?limit=20&order=desc")
for row in recent.get("data", []):
    print(row.get("id"), row.get("model"), row.get("status"), row.get("created_at"))

Confronta il modello e l’ora di creazione; non selezionare alla cieca l’attività più recente. Se necessario, usa next_after come cursore after della richiesta successiva. Se non è possibile identificare l’attività con certezza, contatta l’assistenza anziché inviare di nuovo la richiesta. Un elenco è un’istantanea; per il polling usa i dettagli dell’attività. Il valore output_error di una riga significa che non è stato possibile leggere il risultato, non che la generazione non abbia prodotto nulla o che gli addebiti siano cambiati.

Continua a usare la chiave con cui è stata creata l’attività. In particolare, l’accesso unificato agli elenchi, ai dettagli e ai contenuti delle attività è isolato per token: un’altra chiave dello stesso account non può leggere quelle attività. Un’interruzione locale non dimostra che l’attività sia fallita o che non siano stati applicati addebiti.

5. Errori di migrazione ed errori attuali

La documentazione del legacy adapter di Doubao elenca ID meno recenti all’indirizzo /v1/models/doubao/<id>/predictions, con un involucro input. L’elenco non comprende la versione 5.5. Usa qui l’endpoint 5.5 individuabile e il corpo piatto; non è stato testato alcun errore di generazione tramite il percorso legacy. Copia esattamente l’ID attuale con i trattini, senza presumere che una grafia con i punti sia un alias.

Non mantenere quality, background, aspect_ratio o seed come parametri di primo livello: non sono presenti nello schema attuale di questo modello. L’annuncio di lancio di ByteDance descrive l’output RGBA trasparente nativo, ma lo schema del gateway non espone né background né layer_decomposition. Selezionare PNG da solo non costituisce una procedura verificata per ottenere la trasparenza.

Questi sono errori documentati dell’API unificata per le immagini, non risposte osservate della versione 5.5. Controlla separatamente lo stato HTTP e quello dell’attività, e dirama in base a code, non confrontando l’intero testo del messaggio.

Dove Codice Azione successiva
HTTP 400 schema_violation Correggi i campi dello schema
HTTP 400 capability_not_supported Rimuovi le opzioni non supportate
HTTP 504 sync_timeout Recupera; contatta l’assistenza
HTTP 502 task_status_unavailable Non inviare di nuovo
HTTP 422 output_blocked Modifica il contenuto
HTTP 403 async_not_enabled Attiva la funzionalità delle attività
Attività non riuscita result_delivery_failed Verifica il risultato esistente

Per HTTP 502 task_status_unavailable, la guida afferma:

Non è stato possibile confermare lo stato dell’attività presso il fornitore del modello. Non inviare di nuovo la richiesta. Contatta l’assistenza fornendo l’ID dell’attività o l’ID della richiesta.

Per result_delivery_failed a livello di attività, afferma:

Non è stato possibile consegnare il risultato generato. Non inviare di nuovo automaticamente la richiesta. Contatta l’assistenza fornendo l’ID dell’attività.

Un sync_timeout non dimostra che l’esecuzione non sia mai avvenuta. Conserva error.tid, usa un ID dell’attività solo se è stato effettivamente restituito e chiedi all’assistenza di chiarire gli esiti incerti. In caso di errore di download recuperabile, riprova il recupero anziché la generazione. 410 artifact_expired è un caso diverso: quell’artefatto non può più essere recuperato. Controlla prima i file salvati; se serve ancora una sostituzione, autorizza consapevolmente una nuova generazione a pagamento. Per 429 too_many_downloads, controlla le copie salvate o contatta l’assistenza; aspettare non garantisce che l’accesso venga ripristinato.

La guida rinuncia esplicitamente al costo di generazione per output_blocked, anche se segnalato in un’attività non riuscita. Non estendere questa eccezione a ogni richiesta non riuscita o sottoposta a moderazione; output_policy_violation segue le regole di fatturazione esistenti per la moderazione.

6. Pianifica il budget per l’intero flusso di lavoro, non solo per un risultato

Il resoconto di lancio di Sina Technology indica un costo di circa 0.28 CNY per una modifica quadrata 2K, comprensivo di input e output delle immagini, con i token di testo gratuiti. Si tratta di quanto riportato dalla stampa, non di un tariffario ufficiale verificato né di un preventivo di AIHubMix.

Per fare un esempio, due cicli di modifica a pagamento di un’immagine esistente, ciascuno corrispondente a tale scenario arrotondato, costano circa 2 × CNY 0.28 = CNY 0.56. Sono esclusi la generazione iniziale da testo a immagine, le immagini di riferimento aggiuntive, ulteriori varianti e i nuovi tentativi. Non è l’importo di una fattura misurata.

Per questo esempio di generazione seguita da modifica, usa totale = costo della generazione iniziale + costo della modifica con riferimento. Le pagine esaminate non hanno permesso di stabilire un tariffario ufficiale completo per la versione 5.5; perciò questo tutorial non indica né un totale fisso né un rapporto preciso di risparmio tra la versione nuova e quella precedente.

Prima dell’invio:

  • Conferma l’ID attuale, l’endpoint, il corpo piatto e lo schema del modello.
  • Conserva la chiave nell’ambiente e gli ID delle attività per il recupero.
  • Considera ogni POST un’azione a pagamento distinta, non un nuovo tentativo di download.
  • Controlla lo stato dell’attività e l’immagine salvata prima di modificarla.
  • Ricarica i byte locali con il tipo MIME corretto.
  • Recupera le attività dall’esito incerto prima di valutare un’altra generazione.

Inizia con un’immagine e una modifica mirata; aggiungi altri passaggi solo dopo aver esaminato i file.

Appendice: configurazione condivisa e helper per il download

Salta questa appendice se stai seguendo il flusso di lavoro. Prima di eseguire gli esempi brevi, espandi e carica questo blocco una sola volta nella stessa sessione Python. Configura la sessione e definisce funzioni senza generare immagini. Per recuperare un’attività interrotta in una sessione nuova, ricarica solo questo blocco, non un blocco per la creazione o la modifica.

Espandi l’helper completo — caricalo una volta prima degli esempi brevi; nessuna richiesta per generare immagini
import base64
import os
import time
from pathlib import Path
from urllib.parse import quote, urlsplit

import requests

BASE = "https://aihubmix.com"
IMAGES = "/ai/v1/images"
settings = {
    "model": "doubao-seedream-5-5",
    "size": "2048x2048",
    "n": 1,
    "output_format": "png",
    "response_format": "url",
}
client = requests.Session()
client.headers["Authorization"] = "Bearer " + os.environ["AIHUBMIX_API_KEY"]


def api_json(method, path, body=None):
    try:
        response = client.request(
            method, BASE + path, json=body,
            timeout=(15, 600), allow_redirects=False,
        )
    except requests.RequestException:
        raise SystemExit(
            "Connection interrupted. Recover the existing task before another POST."
        ) from None
    try:
        data = response.json()
    except ValueError:
        raise SystemExit(
            f"HTTP {response.status_code}: non-JSON response; recover before another POST."
        ) from None
    if not isinstance(data, dict):
        raise SystemExit("Unexpected response; recover before another POST.")
    if not 200 <= response.status_code < 300:
        error = data.get("error") or {}
        raise SystemExit(
            f"HTTP {response.status_code}: code={error.get('code')}, "
            f"tid={error.get('tid')}. No automatic generation retry."
        )
    return data


def collect(task, stem, poll=False):
    task_id = task.get("id")
    if not isinstance(task_id, str) or not task_id:
        raise SystemExit("No task ID returned. Recover from the task list; do not resubmit.")
    Path(stem + ".task-id").write_text(task_id + "\n", encoding="utf-8")
    while True:
        status = task.get("status")
        print("Task:", task_id, "status:", status)
        if status == "completed":
            break
        if status not in {"pending", "in_progress"}:
            error = task.get("error") or {}
            raise SystemExit(
                f"Stopped: status={status}, code={error.get('code')}; task={task_id}."
            )
        if not poll:
            raise SystemExit("Task still active. Query the saved ID; do not recreate it.")
        time.sleep(15)
        task = api_json("GET", IMAGES + "/" + quote(task_id, safe=""))

    output = task.get("output") or []
    if not output:
        raise SystemExit("Completed without readable output; investigate the saved task.")
    item = output[0]
    if item.get("b64_json"):
        image_bytes = base64.b64decode(item["b64_json"], validate=True)
    else:
        url = item.get("content_url")
        if not isinstance(url, str):
            raise SystemExit("Missing content_url; investigate the saved task.")
        parsed = urlsplit(url)
        if (parsed.scheme, parsed.netloc) != ("https", "aihubmix.com"):
            raise SystemExit("Unexpected download origin; key was not forwarded.")
        try:
            response = client.get(url, timeout=(15, 120), allow_redirects=False)
        except requests.RequestException:
            raise SystemExit("Download interrupted; recover this task, not a new generation.") from None
        if not 200 <= response.status_code < 300:
            try:
                detail = response.json()
            except ValueError:
                detail = {}
            error = detail.get("error", {}) if isinstance(detail, dict) else {}
            code = error.get("code") if isinstance(error, dict) else None
            if response.status_code == 410 or code == "artifact_expired":
                raise SystemExit("Artifact expired; retrieval cannot recover it. Check saved files first.")
            if code == "too_many_downloads":
                raise SystemExit("Download allowance exhausted; check saved files or contact support.")
            raise SystemExit(
                f"Download HTTP {response.status_code}, code={code}; "
                "inspect the saved task. Retry retrieval only if recoverable."
            )
        image_bytes = response.content
    if not image_bytes.startswith(b"\x89PNG\r\n\x1a\n"):
        raise SystemExit("Expected PNG bytes; stopped before saving or reusing the result.")
    destination = Path(stem + ".png")
    destination.write_bytes(image_bytes)
    print("Saved:", destination)
    return destination

Il timeout di lettura di 600 secondi è una scelta del client, non una promessa sulla latenza del servizio. Il controllo PNG corrisponde al formato di output esplicitamente scelto in questo tutorial; adattalo se scegli JPEG.

FAQ

Quale ID modello e quale endpoint dovrebbe usare Seedream 5.5?
Usa doubao-seedream-5-5 con POST /ai/v1/images/generations e JSON con campi al livello principale. Non dare per scontato che un’altra grafia o un adattatore legacy siano equivalenti.

Questo tutorial include risultati di generazione testati?
No. Il codice si basa sulla documentazione ed è stato sottoposto solo a controlli di sintassi locale e degli helper offline. Non sono state eseguite richieste di inferenza, misurazioni della qualità delle immagini o della latenza, né verifiche di fatturazione.

È necessario usare la modalità asincrona?
No; l’attesa sincrona è l’impostazione predefinita. L’esecuzione in background usa il valore booleano async: true. L’attivazione della funzionalità per le attività a livello di account è un prerequisito per gli endpoint nativi delle attività multimediali, anche quando si attende in modo sincrono.

HTTP 200 significa che l’immagine è stata generata correttamente?
No. Controlla lo stato dell’attività e l’eventuale errore. Un’attività può non riuscire anche se la richiesta HTTP ha esito positivo; scarica l’immagine solo dopo il completamento.

Un URL per scaricare il risultato può essere usato come riferimento per la modifica successiva?
Non darlo per scontato. Scarica l’immagine con la chiave usata per crearla, quindi codifica l’immagine locale come Data URI oppure fornisci un URL dell’immagine accessibile pubblicamente.

Cosa fare dopo un timeout o la perdita della risposta?
Non ripetere automaticamente la generazione. Controlla l’ID dell’attività salvato oppure recuperalo dall’elenco delle immagini con la chiave usata per crearla. Conserva gli ID delle richieste e contatta l’assistenza se l’esito è incerto.

Scegliere PNG garantisce un output trasparente o un addebito di CNY 0.28?
No, in entrambi i casi. Lo schema non prevede un controllo della trasparenza verificato. CNY 0.28 è una cifra approssimativa riportata dalla stampa per un esempio di modifica 2K, non un prezzo di AIHubMix né un prezzo fisso per la generazione da testo a immagine seguita da una modifica.

Continua a leggere: la serie Seedream 5.5

Fonti

  1. Annuncio del lancio di Seedream 5.5 — ByteDance Seed; dichiarazioni del fornitore sulle funzionalità.
  2. Schema attuale dell’endpoint di Seedream 5.5 — AIHubMix; campi della richiesta e vincoli specifici del modello.
  3. API unificata per la generazione di immagini — AIHubMix; attività, download ed errori attuali.
  4. Guida al modello Seedream 5.5 — AIHubMix; ID modello e download autenticati disponibili per un periodo limitato; per gli errori specifici delle route, consulta la documentazione dell’API unificata.
  5. Copertura del lancio di Seedream 5.5 — Sina Technology; scenario con costi di modifica approssimativi, non una tariffa ufficiale.

Un unico gateway per più provider di IA. Pensato per la produzione.

Visita AIHubMix