В этой статье основное внимание уделяется последним двум категориям: опросу TaskHandle асинхронных задач и деталям, ловушкам и языковым различиям потокового ответа chat.
I. TaskHandle — единая абстракция асинхронных задач
Все три SDK оборачивают асинхронные задачи вTaskHandle, предоставляя одинаковые 4 метода:
Два способа вызова для создания задач
Каждый асинхронный ресурс (images.generate / video.generate / audio.generate) имеет параметр wait:
wait=False(по умолчанию): немедленно возвращаетTaskHandle, бизнес-код сам решает, когда опрашивать.wait=True: SDK внутри сразу вызываетhandle.wait(), функция возвращает ответ после завершения. Используйте только если вы уверены, что целевой API обязательно вернет полеstatus: succeeded— некоторые провайдеры не соблюдают это соглашение, что может привести к тому, чтоwaitбудет продолжаться доmax_wait, прежде чем выброситьTimeoutError.
Различия в единицах (⚠️ Обязательно к прочтению)
Единицыpoll_interval и max_wait различаются в трех языках, что является распространенной проблемой при переносе между языками:
Если вы переведете TS{ pollInterval: 3000 }как секунды в Pythonpoll_interval=3000, SDK будет ждать 50 минут, прежде чем опросить второй раз.
Пример: Явный опрос Midjourney на Python
images.generate(..., wait=False)отправляетpromptв Midjourney API, немедленно получаетhandle, не блокируя.handle.wait(poll_interval=3.0, max_wait=180.0)внутренне отправляет POST на/midjourney/tasksкаждые 3 секунды, покаstatusне изменится наsucceededилиfailed, или общее время не превысит 180 секунд, выбрасываяTimeoutError.- После завершения
result["response"]["data"]обычно содержит 4 изображения (по умолчанию Midjourney 2x2 grid).
Пример: Явный опрос на TypeScript
Сравнение синхронной генерации и асинхронных задач
Если ваш провайдер сам по себе синхронно генерирует изображения (NanoBanana / Flux / Seedream), не передавайтеwait:
task_id + /tasks, это синхронная генерация; в ответе синхронной генерации поле data уже содержит окончательный результат.
Внутренний протокол TaskHandle
ВызовTaskHandle.get() выполняет:
response — просто считывает верхний уровень status, поэтому переключение между новыми и старыми ответами не влияет на бизнес-код.
II. SSE потоковый ответ (chat.completions)
chat.completions.create(stream=True) — это в настоящее время единственный потоковый интерфейс в SDK (потоковое аудио / видео пока не поддерживается). Стиль итерации для трех языков различен:
TypeScript
Python
Go
Структура потокового чанка
Каждый чанк является совместимым с OpenAIchat.completion.chunk:
- Первый чанк обычно имеет
delta.role: "assistant", ноcontentпустой. - Промежуточные чанки каждый имеют
delta.content, которые можно напрямую соединять. - Последний чанк
deltaпустой,finish_reasonравенstop/length/content_filter.
Преждевременное отмена
Преждевременная отмена уже учтенных токенов — токены, сгенерированные до момента отмены, все равно будут списаны по факту использования.
Три, тайм-ауты и повторные попытки
Три SDK используют одну и ту же стратегию повторных попыток:
Чтобы отключить повторные попытки: передать
max_retries=0 / maxRetries: 0 / WithMaxRetries(0) при создании клиента.
Цикл опроса асинхронных задач (TaskHandle) сам по себе не подвержен влиянию max_retries — его цикл является бизнес-уровнем, а не HTTP-уровнем, контролируемым max_wait для общего времени.
Четыре, распространенные ловушки
- Синхронные провайдеры не передавать
wait: NanoBanana / Flux / Seedream генерируются синхронно, принудительноеwait=Trueзаставит SDK опрашивать интерфейсtasks, который вообще не будет обновляться. - Различия в единицах TaskHandle: Python — секунды, TS — миллисекунды, при переносе между языками обязательно пересчитывайте.
wait=Trueвсе равно может вызватьTimeoutError: ответ должен соответствоватьstatus in ('succeeded','failed'), чтобы выйти из цикла; если провайдер использует другие имена полей, бизнес-код должен самостоятельноhandle.get()анализировать.- Потоковая отмена: токены, сгенерированные до отмены, уже учтены.
- Повторное использование клиента в одном процессе: SDK имеет встроенный пул соединений, частое создание
new AceDataCloud()/AceDataCloud()может сделать TLS рукопожатие узким местом.

