Wywołujesz createTask i otrzymujesz taskId zamiast obrazu. Teraz potrzebujesz wyniku bez utrzymywania otwartego połączenia przez kilka minut, płacenia dwa razy po przekroczeniu czasu oczekiwania ani utraty zadania po ponownym uruchomieniu procesu.
W skrócie:
- Szybkie modele obrazu w skrypcie: dodaj
?wait=30docreateTask, a często całkowicie pominiesz odpytywanie. - Skrypty, praca lokalna, brak publicznego serwera: odpytuj zadanie w pętli z ograniczoną liczbą iteracji, tak jak w przykładzie poniżej.
- Wszystko, na co czeka użytkownik, wideo lub duża liczba zadań: użyj
callBackUrl, sprawdź podpis, szybko potwierdź odbiór i przetwarzaj zdarzenia z kolejki. - Produkcja: połącz obie metody. Callback jest szybką ścieżką, a okresowa kontrola stanów wychwytuje przypadki, w których callback nie dociera.
Przy bezpośrednim wywołaniu API ?wait=<seconds> (do 60) utrzymuje createTask otwarte do zakończenia zadania. Nadaje się to do modeli obrazu kończących pracę w kilka sekund, ale nie do wideo. callBackUrl (z wielkim B) to publiczny adres HTTPS odbierający wynik, a recordInfo to wywołanie stanu opakowane przez get_task w SDK. Dokumentacja zadań opisuje wszystkie trzy elementy.
Najpierw wypróbuj w Playground
Otwórz Playground seedream-5-0-pro. Wpisz krótki Prompt, ustaw Resolution na 1k, naciśnij Run model i odczytaj wynik w Output; History pokazuje wcześniejsze uruchomienia. Odpytywanie i Webhook automatyzują w aplikacji widoczne tu oczekiwanie; nie tworzą drugiego obrazu.
Wybierz sposób odbierania wyniku
| Twoja aplikacja | Zacznij od | Dlaczego |
|---|---|---|
| Lokalny skrypt lub sporadyczne przetwarzanie wsadowe | Odpytywanie przez SDK | Nie musisz wdrażać publicznego odbiornika |
| Interaktywna aplikacja do obrazów lub wideo | Zweryfikowany Webhook | Reagujesz na koniec generowania bez utrzymywania osobnego oczekującego procesu dla każdego zadania |
| Usługa produkcyjna | Webhook i okresowe uzgadnianie stanu | Pominięty callback nie pozostawia przyjętego zadania bez obsługi |
Wybierz odpytywanie, gdy zadań jest mało lub Twój komputer nie może odbierać publicznych wywołań HTTPS. Wybierz Webhook, gdy użytkownicy czekają w interaktywnej aplikacji lub długie zadania wideo blokowałyby procesy robocze.
Dla zadań z obrazem wejściowym proces przesyłania w SDK wykonuje /files/{fileId}/commit i zwraca URI spicy://; zobacz dokumentację mediów.
Uruchom jedno zadanie przez SDK
Zainstaluj spicyapi, ustaw SPICY_API_KEY i uruchom przykład. Zachowaj map-image.json, aby po przerwaniu wznowić to samo zadanie. Jeśli celowo chcesz inny obraz, użyj nowej nazwy uruchomienia. Python SDK udostępnia metody API, a dokumentacja zadań obejmuje cały cykl życia.
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"])Poprawnie odczytaj odpowiedź
Zadanie zawsze ma jeden z następujących stanów: queued, running, succeeded, failed lub expired. Tylko pierwsze dwa oznaczają, że nadal jest w toku. Zakończ więc pętlę, gdy stan nie jest ani queued, ani running, zamiast czekać wyłącznie na succeeded; w przeciwnym razie nieudane zadanie będzie odpytywane bez końca (starsze rekordy mogą też zawierać stan tylko do odczytu canceled). Link do wyniku znajduje się w output.assets[0].url. Przy bezpośrednim wywołaniu API odczytaj zadanie z obiektu data w opakowaniu odpowiedzi, a nie z jej korzenia. Przyjętego zadania nie można anulować. Opłata jest naliczana wyłącznie za succeeded; failed i expired zwykle zwalniają zablokowaną kwotę.
Co przekroczenie czasu oczekiwania oznacza dla aplikacji
HTTP 202 oznacza przyjęcie zadania, a nie zakończenie generowania. Lokalny limit czasu przerywa oczekiwanie, ale nie anuluje przyjętego zadania. Zachowaj jego ID i wznów je zamiast kupować kolejne generowanie. Termin zwrócony dla zadania wyznacza granicę odzyskiwania, a nie przewiduje czasu renderowania.
- Utracona odpowiedź na wysłanie: zachowaj żądanie i jego klucz, aby podczas odzyskiwania znaleźć pierwotne zadanie.
- Generowanie nie powiodło się: pokaż błąd modelu i pozwól użytkownikowi świadomie wybrać kolejną próbę.
- Generowanie zakończone, plik wciąż oczekuje: nadal czekaj na to samo zadanie; obraz lub wideo jest jeszcze przygotowywany do udostępnienia.
Nowe żądanie otrzymuje nowy klucz idempotencji. Przy odzyskiwaniu tego samego żądania klucz i dane wejściowe pozostają bez zmian. Dokumentacja idempotencji opisuje 24-godzinne okno ponawiania żądania.
Użyj Webhook jako szybkiej ścieżki
Wysyłaj zdarzenia zakończenia do backendu aplikacji, a następnie aktualizuj interfejs użytkownika zwykłym kanałem powiadomień. Callback nie jest bezpośrednią wiadomością do przeglądarki użytkownika.
Odbiornik powinien wykonać cztery czynności:
- Zweryfikować zdarzenie oficjalnym SDK i surową treścią żądania.
- Potwierdzić, że zadanie należy do pracy obsługiwanej przez Twoją aplikację.
- Trwale zapisać zdarzenie i usunąć duplikaty przed potwierdzeniem odbioru.
- Umieścić kopiowanie wyniku i aktualizację aplikacji w kolejce, niezależnie od odpowiedzi HTTP.
Wybierz tę metodę, gdy: masz już backend i chcesz szybko otrzymywać informacje o zakończeniu. Poszukaj innej metody, gdy: to krótki lokalny skrypt bez publicznego odbiornika; odpytywanie jest prostsze.
Osobno sprawdzaj zakończenie zadania i dostarczenie mediów. Poprawnie sformowane zdarzenie może opisywać nieudane zadanie, a udane zadanie może wymagać obsługi plików, zanim aplikacja uzna wynik za gotowy. Dokumentacja Webhook zawiera zasady weryfikacji i dostarczania.
Zachowaj okresowe uzgadnianie stanu
Zapisuj ID każdego przyjętego zadania. Okresowo wracaj do zadań, których aplikacja jeszcze nie rozstrzygnęła, szczególnie po wdrożeniu, awarii sieci lub zmianie sekretu podpisywania. Przekazuj odzyskany wynik do tego samego idempotentnego mechanizmu obsługi zakończenia co Webhook, aby galeria nie otrzymała tego samego pliku dwa razy.
Zachowaj nierozstrzygnięte opłaty w dzienniku aż do zakończenia rozliczenia. Jeśli utracisz lokalne zapisy, historia zadań dla bieżącego klucza pozwala odzyskać ID; integracja produkcyjna opisuje tę ścieżkę.
Skopiuj wyniki przed ich wygaśnięciem
Linki do gotowych wyników są tymczasowe. Kopiuj pliki do pamięci, którą kontrolujesz, z nagłówkiem żądania User-Agent i nazwą pliku zgodną ze zwróconym formatem. Nieudane pobieranie jest powodem do odzyskania istniejącego wyniku, a nie ponownego generowania.
Terminy znajdziesz w artykule o przechowywaniu i dostarczaniu mediów, a proces kopiowania w artykule o trwałym przechowywaniu.
Decyzja
Dla małego skryptu zacznij od odpytywania przez SDK. Dodaj zweryfikowany Webhook, gdy masz usługę interaktywną, i utrzymuj okresowe kontrole na potrzeby odzyskiwania. Zapisane ID zadania łączy wszystkie trzy ścieżki: odbierają wynik jednego generowania zamiast wysyłać zadania zastępcze.
Aby wykonywać więcej prac jednocześnie, dodaj wysyłanie partii z ograniczeniami. Dla pierwszej pary obraz–wideo użyj przewodnika na start.
Powierz wywołanie Agentowi
Użyj Agenta, jeśli ma przygotować dane wejściowe i zwrócić wynik, a Ty chcesz zatwierdzać cenę i wybory twórcze.
- CLI: zapisz
{"prompt": "a folded paper map on a wooden table, overhead", "resolution": "1k", "output_format": "png"}jakoinput.json, a następnie użyjnpx @spicyapi/cli tasks create --model bytedance/seedream-5.0-pro/text-to-image --input-file input.json --wait. CLI prosi o potwierdzenie ceny; zachowaj zwrócone ID zadania do odzyskiwania. - MCP: poproś asystenta o użycie
spicyapi_task_createdlabytedance/seedream-5.0-pro/text-to-image, a następniespicyapi_task_wait. MCP server prosi o potwierdzenie ceny przed utworzeniem zadania. - Skill: zainstaluj przez
npx skills add spicyapi-ai/spicy-skill, a potem poproś$spicyapio wykonanie tego samego procesu i zatrzymanie się na Twoje zatwierdzenie. Skill korzysta ze skonfigurowanego połączenia CLI lub MCP.







