Skip to main content
Ace Data Cloud 上的服務在回應模式上分兩類: 本文重點講後兩類:異步任務的 TaskHandle 輪詢 和 chat 串流回應 的細節、陷阱和跨語言差異。

一、TaskHandle —— 異步任務的統一抽象

三種 SDK 都把異步任務封裝成 TaskHandle,提供同樣的 4 個方法:

創建任務的兩種呼叫方式

每個異步資源(images.generate / video.generate / audio.generate)都有 wait 參數:
  • wait=False(預設):立即返回 TaskHandle,業務代碼自己決定何時輪詢。
  • wait=True:SDK 內部直接調 handle.wait(),函數返回完成後的回應。僅當你確定目標 API 一定會返回 status: succeeded 字段時再用——少數 provider 沒遵守這個約定,會讓 wait 一直轉到 max_wait 才拋 TimeoutError。

單位差異(⚠️ 必看)

poll_interval 和 max_wait 的單位在三種語言裡不一樣,跨語言遷移時是常見踩坑點:
把 TS 的 { pollInterval: 3000 } 當成秒翻成 Python poll_interval=3000,會讓 SDK 等 50 分鐘才輪詢第二次。

示例:Python 明確輪詢 Midjourney

整段代碼做的是:
  1. images.generate(..., wait=False) 把 prompt 提交給 Midjourney API,立即拿到 handle,不阻塞。
  2. handle.wait(poll_interval=3.0, max_wait=180.0) 內部每 3 秒 POST 一次 /midjourney/tasks,直到 status 變成 succeeded 或 failed,或總耗時超過 180 秒拋 TimeoutError。
  3. 完成後 result["response"]["data"] 通常包含 4 張圖(Midjourney 預設 2x2 grid)。

示例:TypeScript 明確輪詢

同步生成 vs 異步任務的取捨

如果你的 provider 本身就是同步出圖(NanoBanana / Flux / Seedream),不要傳 wait:
判斷方法很簡單:如果目標 API 文件裡沒有 task_id + /tasks 這一對,就是同步生成;同步生成的回應裡 data 字段已經包含最終結果。

TaskHandle 內部協議

TaskHandle.get() 呼叫的是:
回應統一結構:
SDK 同時兼容沒有外層 response 包裹的舊版回應——直接讀取頂層 status,所以新舊版回應切換不影響業務代碼。

二、SSE 串流回應(chat.completions)

chat.completions.create(stream=True) 是目前 SDK 裡唯一的串流介面(音頻 / 視頻串流尚未支持)。三種語言的迭代風格各自原生:

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 控制总时长。

四、常见陷阱

  1. 同步 provider 不要传 wait:NanoBanana / Flux / Seedream 都是同步生成,强行 wait=True 会让 SDK 去轮询一个根本不会更新的 tasks 接口。
  2. TaskHandle 单位差异:Python 是秒、TS 是毫秒,跨语言移植时一定换算。
  3. wait=True 仍可能 TimeoutError:响应必须满足 status in ('succeeded','failed') 才会退出循环;如果 provider 用了别的字段名,需要业务代码自己 handle.get() 解析。
  4. 流式取消:取消前生成的 token 已经计费。
  5. 同一 process 内复用 client:SDK 自带连接池,频繁 new AceDataCloud() / AceDataCloud() 会让 TLS 握手成为瓶颈。

了解更多