Artykuł koncentruje się na dwóch ostatnich kategoriach: polling TaskHandle dla zadań asynchronicznych oraz szczegóły, pułapki i różnice językowe w odpowiedziach strumieniowych czatu.
I. TaskHandle — jednolita abstrakcja zadań asynchronicznych
Trzy SDK opakowują zadania asynchroniczne wTaskHandle, oferując te same 4 metody:
Dwa sposoby wywołania do tworzenia zadań
Każdy zasób asynchroniczny (images.generate / video.generate / audio.generate) ma parametr wait:
wait=False(domyślnie): natychmiast zwracaTaskHandle, kod biznesowy decyduje, kiedy przeprowadzić polling.wait=True: SDK wewnętrznie wywołujehandle.wait(), funkcja zwraca odpowiedź po zakończeniu. Używaj tylko wtedy, gdy masz pewność, że docelowe API na pewno zwróci polestatus: succeeded— nieliczni dostawcy nie przestrzegają tej zasady, co sprawi, żewaitbędzie czekać domax_wait, zanim zgłosiTimeoutError.
Różnice jednostek (⚠️ Konieczne do przeczytania)
Jednostkipoll_interval i max_wait są różne w trzech językach, co jest powszechnym punktem zapalnym podczas migracji między językami:
Przekształcenie{ pollInterval: 3000 }z TS na sekundy w Pythonie jakopoll_interval=3000spowoduje, że SDK będzie czekać 50 minut, zanim przeprowadzi drugie polling.
Przykład: Python jawny polling Midjourney
images.generate(..., wait=False)przesyłapromptdo API Midjourney, natychmiast uzyskująchandle, bez blokowania.handle.wait(poll_interval=3.0, max_wait=180.0)wewnętrznie co 3 sekundy wykonuje POST do/midjourney/tasks, ażstatuszmieni się nasucceededlubfailed, lub całkowity czas przekroczy 180 sekund, zgłaszającTimeoutError.- Po zakończeniu
result["response"]["data"]zazwyczaj zawiera 4 obrazy (domyślnie 2x2 grid w Midjourney).
Przykład: TypeScript jawny polling
Wybór między synchronizacją a zadaniami asynchronicznymi
Jeśli twój dostawca sam w sobie generuje obrazy synchronnie (NanoBanana / Flux / Seedream), nie przekazujwait:
task_id + /tasks, to jest to generacja synchronna; w odpowiedzi generacji synchronnej pole data już zawiera ostateczny wynik.
Protokół wewnętrzny TaskHandle
TaskHandle.get() wywołuje:
response — odczytuje bezpośrednio górny poziom status, więc przełączanie między nowymi a starymi odpowiedziami nie wpływa na kod biznesowy.
II. SSE odpowiedź strumieniowa (chat.completions)
chat.completions.create(stream=True) jest obecnie jedynym interfejsem strumieniowym w SDK (strumienie audio / wideo jeszcze nie są obsługiwane). Styl iteracji w trzech językach jest różny:
TypeScript
Python
Go
流式 chunk 的结构
每一帧 chunk 都是一个 OpenAI 兼容的chat.completion.chunk:
- 第一个 chunk 通常带
delta.role: "assistant"但content为空。 - 中间的 chunk 每个带
delta.content,可以直接拼接。 - 最后一个 chunk
delta为空、finish_reason是stop/length/content_filter。
中途取消
提前取消已经计费的 token —— 取消时刻之前生成的 token 还是会按实际消耗扣费。
三、超时和重试
三种 SDK 共享同一套重试策略:
要禁用重试:构造客户端时传
max_retries=0 / maxRetries: 0 / WithMaxRetries(0)。
异步任务(TaskHandle)的轮询本身不受 max_retries 影响——它的循环是业务级的而不是 HTTP 级的,靠 max_wait 控制总时长。
四、常见陷阱
- 同步 provider 不要传
wait:NanoBanana / Flux / Seedream 都是同步生成,强行wait=True会让 SDK 去轮询一个根本不会更新的tasks接口。 - TaskHandle 单位差异:Python 是秒、TS 是毫秒,跨语言移植时一定换算。
wait=True仍可能TimeoutError:响应必须满足status in ('succeeded','failed')才会退出循环;如果 provider 用了别的字段名,需要业务代码自己handle.get()解析。- 流式取消:取消前生成的 token 已经计费。
- 同一 process 内复用 client:SDK 自带连接池,频繁
new AceDataCloud()/AceDataCloud()会让 TLS 握手成为瓶颈。

