Skip to main content
Сервисы на Ace Data Cloud делятся на две категории по режиму ответа: В этой статье основное внимание уделяется последним двум категориям: опросу 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 } как секунды в Python poll_interval=3000, SDK будет ждать 50 минут, прежде чем опросить второй раз.

Пример: Явный опрос Midjourney на Python

Весь код выполняет следующее:
  1. images.generate(..., wait=False) отправляет prompt в Midjourney API, немедленно получает handle, не блокируя.
  2. handle.wait(poll_interval=3.0, max_wait=180.0) внутренне отправляет POST на /midjourney/tasks каждые 3 секунды, пока status не изменится на succeeded или failed, или общее время не превысит 180 секунд, выбрасывая TimeoutError.
  3. После завершения result["response"]["data"] обычно содержит 4 изображения (по умолчанию Midjourney 2x2 grid).

Пример: Явный опрос на TypeScript

Сравнение синхронной генерации и асинхронных задач

Если ваш провайдер сам по себе синхронно генерирует изображения (NanoBanana / Flux / Seedream), не передавайте wait:
Метод определения очень прост: если в документации целевого API нет пары task_id + /tasks, это синхронная генерация; в ответе синхронной генерации поле data уже содержит окончательный результат.

Внутренний протокол TaskHandle

Вызов TaskHandle.get() выполняет:
Ответ имеет единую структуру:
SDK также совместим с устаревшими ответами без внешнего обертывания response — просто считывает верхний уровень status, поэтому переключение между новыми и старыми ответами не влияет на бизнес-код.

II. SSE потоковый ответ (chat.completions)

chat.completions.create(stream=True) — это в настоящее время единственный потоковый интерфейс в SDK (потоковое аудио / видео пока не поддерживается). Стиль итерации для трех языков различен:

TypeScript

真实运行结果:

Python

真实运行结果:

Go

真实运行结果:

Структура потокового чанка

Каждый чанк является совместимым с OpenAI chat.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 для общего времени.

Четыре, распространенные ловушки

  1. Синхронные провайдеры не передавать wait: NanoBanana / Flux / Seedream генерируются синхронно, принудительное wait=True заставит SDK опрашивать интерфейс tasks, который вообще не будет обновляться.
  2. Различия в единицах TaskHandle: Python — секунды, TS — миллисекунды, при переносе между языками обязательно пересчитывайте.
  3. wait=True все равно может вызвать TimeoutError: ответ должен соответствовать status in ('succeeded','failed'), чтобы выйти из цикла; если провайдер использует другие имена полей, бизнес-код должен самостоятельно handle.get() анализировать.
  4. Потоковая отмена: токены, сгенерированные до отмены, уже учтены.
  5. Повторное использование клиента в одном процессе: SDK имеет встроенный пул соединений, частое создание new AceDataCloud() / AceDataCloud() может сделать TLS рукопожатие узким местом.

Узнать больше