Aller au contenu principal

createTask, et ensuite ? Interrogation ou Webhooks pour les tâches de génération asynchrones

Les modèles renvoient une taskId. Choisissez interrogation ou Webhooks et reprenez après un délai dépassé sans payer deux fois.

Auteur
SpicyAPI Engineering
Publié
Lecture
8 min de lecture
Mis à jour
Un chemin sinueux ponctué de points de contrôle circulaires longe une voie dorée directe vers une sphère lumineuse.

Vous avez appelé createTask et reçu une taskId au lieu d’une image. Il vous faut maintenant obtenir le résultat sans garder une connexion ouverte pendant des minutes, payer deux fois après un dépassement de délai ni perdre la tâche au redémarrage de votre processus.

En bref :

  • Modèles d’image rapides dans un script : ajoutez ?wait=30 à createTask pour souvent éviter toute interrogation périodique.
  • Scripts, développement local, sans serveur public : interrogez la tâche avec une boucle bornée comme celle ci-dessous.
  • Toute tâche attendue par un utilisateur, vidéo ou volume important : utilisez callBackUrl, vérifiez la signature, accusez réception rapidement et traitez les événements depuis une file d’attente.
  • Production : combinez les deux. Le rappel constitue la voie rapide ; une vérification périodique des états récupère les rappels qui n’arrivent jamais.

Dans l’API directe, ?wait=<seconds> (jusqu’à 60) maintient createTask ouvert jusqu’à la fin de la tâche. Cela convient aux modèles d’image qui terminent en quelques secondes, mais pas à la vidéo. callBackUrl (avec un B majuscule) est l’adresse HTTPS publique qui reçoit le résultat, et recordInfo est l’appel d’état encapsulé par get_task dans le SDK. La référence des tâches décrit ces trois éléments.

Essayez d’abord dans Playground

Ouvrez le Playground de seedream-5-0-pro. Saisissez un Prompt court, réglez Resolution sur 1k, appuyez sur Run model et consultez le résultat dans Output ; History répertorie les exécutions précédentes. L’interrogation et les Webhooks automatisent pour votre application l’attente que vous observez ; ils ne créent pas une deuxième image.

Choisissez comment obtenir le résultat

Votre applicationCommencez parPourquoi
Script local ou traitement occasionnel par lotsInterrogation via le SDKAucun récepteur public à déployer
Application interactive d’image ou de vidéoWebhook vérifiéRéagir à la fin de la génération sans garder un processus en attente pour chaque tâche
Service en productionWebhook et vérification de rapprochementUn rappel manqué ne laisse pas une tâche acceptée sans suivi

Choisissez l’interrogation lorsque le nombre de tâches est faible ou que votre machine ne peut pas recevoir d’appels HTTPS publics. Choisissez les Webhooks lorsque des utilisateurs attendent dans une application interactive ou que de longues tâches vidéo immobiliseraient les processus de travail.

Pour les tâches prenant une image en entrée, le flux d’envoi du SDK effectue /files/{fileId}/commit et renvoie une URI spicy:// ; consultez la documentation des médias.

Exécutez une tâche avec le SDK

Installez spicyapi, définissez SPICY_API_KEY et exécutez l’exemple. Conservez map-image.json pour reprendre la même tâche après une interruption. Pour une image volontairement différente, utilisez un nouveau nom d’exécution. Le Python SDK fournit les méthodes de l’API ; la référence des tâches couvre le cycle de vie complet.

python
import json
import os
import time
import uuid
from pathlib import Path
from spicyapi import SpicyClient, output_assets

client = SpicyClient()

def run(model, inputs, name):
    path = Path(name + ".json")
    request = {"model": model, "input": inputs}
    saved = json.loads(path.read_text()) if path.exists() else {"request": request, "key": str(uuid.uuid4())}
    if saved["request"] != request:
        raise ValueError("Changed input needs a new run name; preserve the old attempt.")
    def save():
        temporary = path.with_suffix(".tmp")
        temporary.write_text(json.dumps(saved))
        temporary.chmod(0o600)
        temporary.replace(path)
    if not saved.get("taskId"):
        if time.time() - saved.get("sentAt", time.time()) >= 23 * 3600:
            raise RuntimeError("Reconcile the saved attempt before submitting again.")
        if "quote" not in saved:
            saved["quote"] = client.quote_task(model=model, input_data=inputs)
            if input(f"Maximum ${saved['quote']['maxCharge']}. Create? [y/N] ") != "y":
                raise SystemExit("Stopped without creating this task.")
        saved.setdefault("sentAt", time.time())
        save()
        quote = saved["quote"]
        task = client.create_task(model=model, input_data=inputs,
            idempotency_key=saved["key"], quote_id=quote["quoteId"], expected_cost=quote["estimatedCost"])
        saved["taskId"] = task["taskId"]
        save()
    print("Task:", saved["taskId"])
    for _ in range(360):
        task = client.get_task(saved["taskId"])
        if task["state"] not in {"queued", "running"} and task["state"] != "succeeded":
            raise RuntimeError(str(task.get("errorMessage", task["state"])))
        if task["state"] == "succeeded":
            assets = output_assets(task)
            if assets and assets[0].get("unavailable"):
                raise RuntimeError("Output unavailable; keep the task ID for reconciliation.")
            if assets and assets[0].get("url") and not assets[0].get("pending"):
                return assets[0]
        time.sleep(5)
    raise TimeoutError("Rerun the same saved attempt to resume; no new task is needed.")

asset = run("bytedance/seedream-5.0-pro/text-to-image", {
    "prompt": "a folded paper map on a wooden table, overhead", "resolution": "1k", "output_format": "png"
}, "map-image")
print(asset["url"])

Lisez correctement la réponse

Une tâche est toujours dans l’un des états suivants : queued, running, succeeded, failed ou expired. Seuls les deux premiers correspondent à une tâche encore en cours. Arrêtez donc la boucle dès que l’état n’est ni queued ni running, au lieu d’attendre uniquement succeeded, sinon une tâche échouée sera interrogée indéfiniment (les anciens enregistrements peuvent aussi afficher l’état en lecture seule canceled). Le lien du résultat se trouve dans output.assets[0].url. Avec l’API directe, lisez la tâche dans l’objet data de l’enveloppe, et non à la racine de la réponse. Une tâche acceptée ne peut pas être annulée, et seul succeeded est facturé ; failed et expired libèrent normalement le montant réservé.

Ce qu’un dépassement de délai signifie pour votre application

HTTP 202 signifie qu’une tâche a été acceptée, pas que la génération est terminée. Un dépassement de délai local arrête l’attente ; il n’annule pas la tâche acceptée. Conservez son ID et reprenez-la au lieu de payer une autre génération. L’échéance renvoyée pour une tâche marque la limite de récupération, pas une prévision du temps de rendu.

  • Réponse d’envoi perdue : conservez la requête et sa clé pour que la récupération puisse retrouver la tâche d’origine.
  • Génération échouée : affichez l’erreur du modèle et laissez l’utilisateur choisir délibérément une nouvelle tentative.
  • Génération réussie, fichier en attente : continuez d’attendre cette tâche ; l’image ou la vidéo est encore en préparation pour sa livraison.

Une nouvelle requête reçoit une nouvelle clé d’idempotence. Pour récupérer la même requête, gardez sa clé et ses entrées inchangées. La référence de l’idempotence décrit la fenêtre de réexécution de 24 heures.

Utilisez les Webhooks comme voie rapide

Envoyez les événements de fin à votre backend, puis actualisez l’interface utilisateur par votre canal habituel de notification. Un rappel n’est pas un message direct au navigateur de l’utilisateur.

Le récepteur doit faire quatre choses :

  1. Vérifier l’événement avec le SDK officiel et le corps brut de la requête.
  2. Confirmer que la tâche appartient à un travail géré par votre application.
  3. Enregistrer durablement l’événement et éliminer les doublons avant d’en accuser réception.
  4. Mettre en file d’attente la copie des résultats et la mise à jour de l’application, séparément de la réponse HTTP.

À choisir si : vous avez déjà un backend et souhaitez des notifications de fin rapides. Cherchez une autre solution si : il s’agit d’un petit script local sans récepteur public ; l’interrogation est plus simple.

Vérifiez séparément la fin de la tâche et la livraison des médias. Un événement bien formé peut décrire une tâche échouée, tandis qu’une tâche réussie peut nécessiter un traitement des fichiers avant que votre application la signale comme prête. La documentation des Webhooks précise les règles de vérification et de livraison.

Conservez une vérification de rapprochement

Enregistrez l’ID de chaque tâche acceptée. Revisitez périodiquement les tâches non résolues par votre application, notamment après un déploiement, une panne réseau ou une rotation du secret de signature. Faites passer un résultat récupéré par le même gestionnaire de fin idempotent qu’un Webhook, afin que la galerie ne reçoive pas deux fois le même fichier.

Gardez les opérations de facturation non résolues dans le journal jusqu’à la fin du règlement. Si les enregistrements locaux sont perdus, l’historique des tâches de la clé actuelle permet de retrouver les ID ; l’intégration en production décrit cette procédure.

Copiez les résultats avant leur expiration

Les liens des résultats prêts sont temporaires. Copiez les fichiers vers un stockage que vous contrôlez, avec un en-tête de requête User-Agent et un nom de fichier correspondant au format renvoyé. Un échec de téléchargement justifie de récupérer le résultat existant, pas de le générer à nouveau.

Consultez la conservation et la livraison des médias pour les échéances et le stockage durable pour le processus de copie.

La décision

Commencez par l’interrogation via le SDK pour un petit script. Ajoutez des Webhooks vérifiés lorsque vous avez un service interactif, et conservez la vérification périodique pour la récupération. L’ID de tâche enregistré relie ces trois voies : elles récupèrent une seule génération plutôt que de soumettre des tâches de remplacement.

Pour davantage de travaux simultanés, ajoutez une distribution bornée des lots. Pour votre premier duo image-vidéo, utilisez le guide de démarrage.

Confiez l’appel à un Agent

Utilisez un Agent si vous voulez qu’il prépare les entrées et renvoie le résultat pendant que vous approuvez le prix et les choix créatifs.

  • CLI : enregistrez {"prompt": "a folded paper map on a wooden table, overhead", "resolution": "1k", "output_format": "png"} dans input.json, puis utilisez npx @spicyapi/cli tasks create --model bytedance/seedream-5.0-pro/text-to-image --input-file input.json --wait. La CLI vous fait confirmer le prix ; conservez l’ID de tâche renvoyé pour la récupération.
  • MCP : demandez à votre assistant d’utiliser spicyapi_task_create pour bytedance/seedream-5.0-pro/text-to-image, puis spicyapi_task_wait. Le MCP server demande une confirmation du prix avant la création.
  • Skill : installez avec npx skills add spicyapi-ai/spicy-skill, puis demandez à $spicyapi d’exécuter le même flux et de s’arrêter pour obtenir votre approbation. Le Skill utilise une connexion CLI ou MCP configurée.

Aussi en English · 日本語 · 한국어 · Deutsch · Español · Português (Brasil) · Русский · Italiano · Polski

Essayez par vous-même

Vous ne payez que ce que vous lancez : ni forfait, ni abonnement.

Créé avec MiniMax H3 · ByteDance Seedance 2.0 Fast